我不是 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
指令(尾调用优化)。