2

我正在创建一个包含日志记录类的 Windows DLL 库,该类中的日志函数只是像这样调用 fprintf 以进行测试:

fprintf(stderr, "DEBUG: %s\n", "Hello");

现在,如果我从我的其他项目(使用库)的任何文件中的任何函数中使用它,这个调用就可以正常工作,但是如果我将它放在我的库中的任何位置,带有日志记录类,它根本不会打印任何东西。
我可以看到它正确运行函数(使用简单的 exit(0); 进行测试)。

现在我对 c/c++ 中的整个库概念仍然有点新,所以可能有些东西我只是不明白,但否则我不知道为什么它不起作用。

我试着在这里和谷歌上搜索,但我找不到其他人有同样的问题。
我使用 VC++ 2010

编辑:我想到了传递文件指针而不是仅使用库中的 stderr,这会导致抛出异常(文件的 _tmpfname 指针在抛出时为 NULL,我不确定这是正确的)

4

1 回答 1

2

我会避免对任何生产代码执行此操作(尽管可以进行测试)。标准 I/O 流属于应用程序,而DLL 是家里的客人。如果您想提供调试输出,请允许应用程序设置用于记录的回调函数,例如:

// In your DLL's header file:
typedef void (*LogFunc)(const char *, ...);
void DLLEXPORT SetLogFunction(LogFunc logFunc);

// In your DLL's source file:
LogFunc g_LogFunc;
void DLLEXPORT SetLogFunction(LogFunc logFunc)
{
    g_LogFunc = logFunc;
}

...
// Then, instead of calling fprintf(stderr, "blah"), do this:
g_LogFunc("blah");

如果您只是为了测试而这样做,您可以直接写入stderr,但请记住,DLL 和应用程序必须链接到相同版本的 C 运行时才能使其工作。C 运行时本身就是一个 DLL,如果您的 DLL 和应用程序指定了不同版本的 C 运行时,您最终会将 C 运行时的两个单独副本加载到内存中,每个副本都有自己的stderr含义。当它们不同时,就会发生坏事。

在 Visual Studio 中,要设置您正在使用的 C 运行时库,请打开项目设置并转到配置属性 → C/C++ → 代码生成 → 运行时库,并确保 DLL 和应用程序都设置为准确相同的值(通常是“多线程 DLL (/MD)”或“多线程调试 DLL (/MDd)”,具体取决于您构建的是调试版本还是发布版本)。

于 2012-08-02T23:18:04.587 回答