混合C / C ++代码产生"未定义的符号"共享库

时间:2015-02-23 18:18:03

标签: c++ c qt shared-libraries dlopen

这个问题困扰了我一个星期,所以我想最后可能是时候向你们寻求帮助了。简而言之,这就是故事:

我们正在使用Qt / C ++开发内部嵌入式服务器。它是一个非常简单的服务器,它处理客户端请求并通过dlopen()/ dlsym()调用加载适当的函数来执行特定于供应商的操作。这意味着供应商只需在我们定义的方式中为我们提供C语言中的.so文件及其功能(对我们来说是透明的)。这将用C编写,因为它需要做很多低级别的事情,而我们的服务器在Qt中,因为我们计划最终有一个前端。

这是一些伪代码:

在我们的main.cpp文件中(这是用C方式编写的,但是使用了Qt mkspec中定义的g ++编译器,使用-ldl和-rdynamic编译导出所有符号):

  • dlopen()vendor.so文件(尝试使用RTLD_NOW和RTLD_LAZY)
  • dlsym()vendor.so init()方法(这将调用供应商的init方法,它将设置此"供应商插件的名称/属性"通过我们内部的setter方法代码,调用此plugin_set_name(args ...))

在共享头文件(shared.h)中(两个代码库都将使用它;我们的将具有结构的完整定义,供应商将只具有setter / getter的原型):

  • extern" C" int plugin_set_name(args ...)

在供应商main.c文件中(使用gcc,-fPIC和-shared编译)

  • 如上所述的init()函数的实现

基本上,正在发生的事情是C ++代码将使用dl调用从C .so库加载init()函数,然后C .so库将调用C ++中定义的函数代码(在本例中为plugin_set_name)。这甚至可能吗?两者都没有相互关联,因为它们是相互独立编译的,并且使用不同的编译器(gcc vs g ++)。

我得到的错误是运行时:"未定义的符号:plugin_set_name" (所以它找到并进入库的init()方法就好了)。当我使用gcc和直接的C代码来完成所有事情时,它完美无瑕地工作,所以我知道它不是代码,而是混合C / C ++的东西。我也理解使用extern" C"防止名称损坏,并使用nm / readelf确定没有任何类型的重整。有任何想法吗?最好的方法是什么?

1 个答案:

答案 0 :(得分:2)

不知何故,这只是神奇地在今天起作用。我无法解释。我只是在共享头部周围有外部“C”声明,所以在shared.h中:

#ifdef __cplusplus
extern "C" {
#endif

plugin_set_name(args...)
other_shared_functions

#ifdef __cplusplus
}
#endif

但我总是这样。在任何一种情况下,它现在都可以使用在C中编译的供应商插件和在Qt和C ++中编译的服务器。我认为问题是将所有外部放置在哪里以及g ++链接标志(rdynamic至关重要)的组合。谢谢。只需将此放在此处以防其他人遇到同样的问题。