正确使用可变参数函数C API与C++实现

ercv8c1e  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(130)

我想在一个混合的C/C应用程序中使用C日志库。遗留应用程序充满了printf风格的日志记录。新图书馆也支持这一点。
C文件是用C编译器编译的,所以我不能在其中包含C日志头。
我正在努力创建一个带有C风格头文件和C
源文件的C++库:

//logger.h
extern "C" {
    extern void RS_LOG_INFO_PRIVATE(const char* fmt, ...);
    #define LOG_INFO(...)  RS_LOG_INFO_PRIVATE(__VA_ARGS__)
}

//logger.cpp
#include "logger.h"
#include <aws/core/utils/logging/LogMacros.h>
#include <utility>
template<class... Args>
void RS_LOG_INFO_PRIVATE(const char* fmt, Args&&... args) {    
    AWS_LOG_DEBUG(fmt, std::forward<Args>(args)...);
}

//main file
#include "logger.h"

int main() {
    LOG_INFO("test %s", "me");
}

我得到undefined reference to 'RS_LOG_INFO_PRIVATE'
nm -C也验证了这一点:

U RS_LOG_INFO_PRIVATE(char const*, ...)

有没有办法解决这个问题,或者我应该改变我的方法?

flseospp

flseospp1#

如果您正在重新编译应用程序,可以认真考虑从C编译器更改为C编译器。这样做会导致各种编译问题,但解决这些问题通常并不比对C编译方式进行一些重大修改(例如,新的编译器供应商,或提高编译器警告级别)更困难。通过这种方式,您可以避免使用C风格的变量参数,并将其替换为可变参数模板调用。
如果切换到C
编译器是不可行的,那么你必须让你的头文件充当C编译器的C头文件,并充当C编译器的C头文件(或为不同的编译器维护两个不同的头文件)。
假设你的C和C++编译器有兼容的CABI,那么检测使用哪个编译器的常用机制是__cplusplus宏。

#pragma once

#ifdef __cplusplus
// ... C++ stuff
#endif

一个常见的技巧是通过使用extern "C" Package C头文件的内容,使C头文件可用于C++头文件。您似乎尝试过这样做,但没有检查__cplusplus

#pragma once

/* A C header file made to work for C++ */

#ifdef __cplusplus
extern "C" {
#endif

/* rest C stuff ... */

#ifdef __cplusplus
}
#endif

C编译器无法理解extern "C"是什么,因此它被__cplusplus检查隐藏,这将是为C编译器定义的。
变量参数函数的库实现在C
中实现时不应该有所不同(#include头文件)。然后,实现将调用实际完成调用所需的任何C++实现代码。

相关问题