在没有extern“C”的情况下在c ++中使用dlsym

时间:2013-08-07 06:56:08

标签: c++ g++

我有一个系统,我给用户一个函数原型,用户必须实现它。现在,我使用g ++编译此文件,并使用dlopen和dlsym动态加载它以进一步处理它。现在,我在这里读到:

c++ dlopen mini-howto

要加载c ++函数,我们必须在函数之前使用extern“C”。现在,问题是,我不想向用户展示工作原理。我不想在函数之前显示用户extern“C”。

有什么办法可以避免吗?

3 个答案:

答案 0 :(得分:1)

您可以直接使用mangled C++名称。

如果您有例如一个C ++函数void my_plugin(int foo),C ++编译器将破坏该名称。 一旦知道了损坏的函数名,就可以在该名称上使用dlopen()。

e.g。

# nm libmyplugin.so |grep my_plugin
00000000 T _Z9my_plugini

所以这里我们的函数名为_Z9my_plugini,你可以做

 func = dlsym(handle, "_Z9my_plugini");

传统上不同的编译器可能会以不同的方式破坏名称,因此这可能非常脆弱,而现在大多数C ++编译器都会以一种标准的方式在给定平台上修改名称。

但是,您的用户将是程序员,他们通常会理解将条目公开为动态加载的库extern "C"

答案 1 :(得分:1)

由于您使用的是C ++,为什么不只导出一个(或两个)函数,这些函数只返回指向某种纯虚拟类的指针,比如IMyModule?一个(或两个)导出的extern "C"函数类似于extern "C" IMyModule * create_instance_IMyModule();(和extern "C" void delete_instance_IMyModule(IMyModule const *);)。

答案 2 :(得分:0)

每个声明之前extern "C"的另一个替代方法是使用块样式语法:

extern "C" {

void my_callback();
int other_functionality( foo * );

}

extern "C" {和右括号}通常包含在宏中,这些宏以__cplusplus内置宏为条件,因此标题也可以从纯C中使用。也包含你发现令人反感的部分。

无论如何,我看不出有什么大不了的。如果用户可以使用C ++编写,那么当库文档告诉他们时,他们应该能够在extern "C"中包含他们的C接口函数原型。