【问题标题】:Calling fprintf from dynamic library (c++)从动态库调用 fprintf (c++)
【发布时间】:2012-08-03 07:18:04
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 您的 DLL 和主应用程序是否都链接到同一个 C 运行时版本?
  • 我在哪里可以找到这些信息?
  • 查看依赖标签下“项目”的清单,我得到版本 9.0.21022.8 但是库的清单不会生成依赖标签或在其他地方显示 C 运行时版本:(

标签: c++


【解决方案1】:

我会避免对任何生产代码执行此操作(尽管可以进行测试)。标准 I/O 流属于应用程序,the DLLs are guests in the house。如果你想提供调试输出,允许应用设置一个回调函数来记录日志,例如:

// 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 运行时库,请打开您的项目设置并转到 Configuration Properties → C/C++ → Code Generation → Runtime Library 并确保两者DLL 和应用程序设置为完全相同的值(通常是“多线程 DLL (/MD)”或“多线程调试 DLL (/MDd)”,具体取决于您构建的是调试版本还是发布版本) .

【讨论】:

  • 是的,我会避免在生产代码中以任何方式从 DLL 中使用stderr——在这种情况下,我总是会使用回调。这样一来,与 stderr 的所有交互都发生在主应用程序中,并且不会出现多个冲突的 C 运行时导致问题。
  • 抱歉随机删除评论,我在发布 xD 后才意识到你的意思非常感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 2020-02-06
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
相关资源
最近更新 更多