我有一个项目,我需要区分属于linux守护程序(用C语言编写(和简单的Linux程序(用C++编写(的文件。这两个项目使用了 2 个共享文件 (helpers_functions(。守护程序和程序具有不同的日志记录系统。守护程序写入文件,程序写入标准输出。
当我想在两个程序的通用函数中记录某些内容(在文件中(时出现问题helper_functions。我不想通过参数传递,这是程序 A 或程序 B。
我已经编译了属于带有 g++ 标志 -D 的单独程序的文件,但是当我想从公共文件记录时,我该怎么办?我无法定义任何东西,因为我不知道何时将其用于程序 A,或何时用于程序 B。
您可以添加全局变量
const int iamprogram = ...;
它被定义为在程序A中PROGRAM_A
,在程序B中PROGRAM_B
以解决眼前的问题。您还可以使此变量直接包含要记录到的文件:
const char *program_logfile = "/path/to/logfileA";
从长远来看,我建议你重构你的代码,这样公共代码就不依赖于它所属的程序。对于您还想将代码用于第三个程序的情况,这更具可维护和可扩展性。
我不是 100% 确定运行时动态链接是否可以处理这个问题。 如果您将帮助程序函数静态链接到每个可执行文件中,它肯定会起作用。
在两个程序中提供具有相同 API 的日志记录函数。 让想要记录某些内容的库函数调用此函数。 他们获得使用库的程序提供的实现。
每个程序和库包含的头文件
// common_log.h
#ifdef __cplusplus
extern "C" // for the following definition only, no opening {
#endif
// used by code that can be part of either program
void common_log(char *msg, int log_prio);
tty C++程序中的实现(简单日志记录(:
#include "common_log.h"
#include <iostream>
// used by the rest of the C++ program
void simple_logger(char *msg) {
cerr << msg;
}
extern "C" void common_log(char *msg, int log_prio) {
simple_logger(msg);
}
守护程序 C 程序中的实现:
#include "common_log.h"
#include <stdio.h>
#include <errno.h>
static FILE *logfp;
static int log_level;
// used by daemon code
void fancy_logger(char *msg, int log_prio) {
if (log_prio < log_level)
return;
if (EOF == fputs(logfp, msg)) {
perror("failed to write log message to log file: ");
}
}
// or use linker tricks to make common_log an alias for fancy_log,
// if they both have the same signature and you don't need to do anything in the wrapper.
//extern "C" // this is already C
void common_log(char *msg, int log_prio) {
fancy_logger(msg, log_prio);
}
这要求链接器能够使用链接到它的程序中的符号解析库中未定义的符号。 我认为这是有效的,类似于提供全局变量弱定义的库,因此主程序的定义优先。
如果simple_logger
也可以extern "C"
并具有相同的签名,则可以将它们命名为相同并避免使用反弹功能。 或者,如果公共函数可以是任何一个程序中程序自己的日志记录函数的别名,我认为有链接器技巧可以实际做到这一点,而不是编译为单个jmp
指令(尾部调用优化(。
您可以实现一个回调来获取特定于程序的输出。有两个好处:从公共部分到应用程序没有依赖关系(公共部分定义接口(,您可以在运行时和编译时进行区分,这为未来的开发提供了更多的空间,例如通过命令行参数或用户交互更改输出。
在下面的示例中,我们将公共代码部分称为"库"。
图书馆.h
typedef void (*logFunc_t)( logBuffer_t );
void setLogOutput( logFunc_t applicationLog );
图书馆.c
logFunc_t logger; // might be good idea to initialize to an empty function, but omitted here
void setLogOutput( logFunc_t applicationLog )
{
logger = applicationLog;
}
void log( logBuffer_t data )
{
logger( data );
}
应用程序.cpp/应用程序.c
// here you should have the extern "C" in C++ application to ensure linkage compatibility
// I am assuming your shared code is C
extern "C" void myLogger( logBuffer_t data );
int main( int argc, char* agv[] )
{
setLogOutput( &myLogger );
// ...do your thing
return 0;
}
void myLogger( logBuffer_t data )
{
// ...log wherever
}