我的项目我需要区分文件属于linux守护进程(在C中)和简单的linux程序(用C ++编写)。这两个项目使用了2个共享文件(helpers_functions)。守护进程和程序有不同的日志系统。守护进程写入文件,程序到stdout。
当我想在两个程序的常用函数中记录某些内容时(在helper_functions文件中),会出现问题。我不想传递via参数,这是程序A,或程序B。
我编译的文件属于带有g ++标志 -D 的单独程序,但是当我想从常用文件登录时,我该怎么办?我无法定义任何内容,因为我不知道何时将其用于程序A,或何时用于程序B.
答案 0 :(得分:1)
您可以添加全局变量
const int iamprogram = ...;
在程序A中定义为PROGRAM_A
,在程序B中定义为PROGRAM_B
以解决当前问题。您还可以使此变量直接包含要记录的文件:
const char *program_logfile = "/path/to/logfileA";
从长远来看,我建议你重构代码,使公共代码不依赖于它所属的程序。对于您希望将代码用于第三个程序的情况,这更易于维护和扩展。
答案 1 :(得分:1)
您可以实现回调以获取程序特定的输出。有两个好处:没有从公共部分到应用程序的依赖(公共部分定义接口),您可以在运行时与编译时区分,这为将来的开发提供了更多的空间,例如通过命令行参数或用户更改输出相互作用。
在下面的示例中,我们将公共代码部分称为“库”。
<强> library.h 强>
typedef void (*logFunc_t)( logBuffer_t );
void setLogOutput( logFunc_t applicationLog );
<强> LIBRARY.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 );
}
application.cpp / application.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
}
答案 2 :(得分:0)
我不是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);
#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);
}
#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
指令(尾调用优化)