将 C++ 库链接到具有非 C++ 主函数的程序

Posted

技术标签:

【中文标题】将 C++ 库链接到具有非 C++ 主函数的程序【英文标题】:Linking a C++ library to a program which has a non-C++ main function 【发布时间】:2012-10-03 23:05:52 【问题描述】:

给定一些 C++ 函数(使用 STL),您能否在具有未使用 C++ 编译器编译的 main 函数的程序中使用它们?你能避免将该程序与 C++ 编译器联系起来吗?

我知道接口必须是外部“C”函数并且它们不应该抛出异常。

通过搜索网络,我发现许多来源暗示这是不可能的,例如:

http://www.gnu.org/software/libtool/manual/html_node/C_002b_002b-libraries.html#C_002b_002b-libraries “因此,运行 ld 链接 C++ 程序或库被视为失败。” http://www.velocityreviews.com/forums/t591272-re-linking-a-c-program-to-a-c-library-which-uses-stl.html “调用 C++ 库的 C 主程序从一开始就注定要失败”

但我也发现了这个: http://wewantarock.wordpress.com/2010/11/01/working-around-the-static-libstdc-restriction/

我是这样理解的:解决方法是构建一个共享库。 您使用 C++ 编译器链接共享库,而共享库本身就是一种“程序”(具有 DLLMain 之类的启动/拆卸函数,而不是普通的 main 函数)。使用共享库的程序不需要知道它是一个 C++ 库。

我理解正确吗?

有什么问题吗?

编辑 1:我试过了 - 成功了。我用 libtool 构建了我的共享库, 并且可以通过与普通的链接来使用它

cc c_main_program.o -lmy_cpp_library -o c_main_program

更新问题,实验成功后:有没有什么catch可以 稍后让我感到惊讶(例如在其他平台上,或者当我在全局变量中使用构造函数时,......)

【问题讨论】:

【参考方案1】:

只要您导出接口是使用已知调用约定的直接 c 函数,在内部使用 STL 就没有问题。 Dll 已经构建,不需要调用链接器或编译器来使用它们。

c++ 的问题在于 c++ 的二进制格式依赖于实现,因此无法保证使用不同编译器构建的源代码兼容代码将是二进制兼容的。链接模板存在单独的问题,因为库中仅包含模板的实例化具体版本,编译器必须查看模板的定义以避免两次声明它(对于大多数编译器)。

c 没有此类问题 c 函数具有定义的接口,并且数据类型的布局也是已知的,因此从单独的编译器动态加载没有问题。但这意味着您只能使用 c 的类型和功能。

如需更详尽的讨论,请查看this

【讨论】:

全局对象的构造函数和析构函数呢? 首先,在非 c++ 程序中很难访问它们,因为您必须将它们外部化并以某种方式找到符号,然后访问这些函数几乎是不可能的。但它们当然可以被你的函数使用,而不是客户端。 因此,如果您将this code 链接到一个C 程序并调用compute(),您会期望它返回正确的值吗?什么会导致构造函数被调用? 是的。在 dllmain 之前初始化,这来自 dllmain 文档“如果您的 DLL 与 C 运行时库 (CRT) 链接,则 CRT 提供的入口点调用全局和静态 C++ 对象的构造函数和析构函数。因此,这些限制对于 DllMain 也适用于构造函数和析构函数以及从它们调用的任何代码。” 是的。看起来你是对的......我在后台进行了一些测试,我很确定这不会起作用。

以上是关于将 C++ 库链接到具有非 C++ 主函数的程序的主要内容,如果未能解决你的问题,请参考以下文章

如何将本机 C++ 静态库链接到托管 C++ 程序集

C++:从函数访问主变量的最简单方法?

选择在 Visual C++ 2010 中使用哪个主函数

是否可以定义指向构造函数的函数指针?

Linux 动态链接库(.so)的使用

具有行主矩阵特征 C++ 的平方欧几里得距离