4

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

c++ dlopen mini-howto

要加载 c++ 函数,我们必须在函数之前使用 extern "C"。现在,问题是,我不想向用户展示事情是如何工作的。我不想在函数之前显示用户 extern "C"。

有什么办法可以避免吗?

4

3 回答 3

4

您可以直接使用损坏的 C++名称。

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

例如

# nm libmyplugin.so |grep my_plugin
00000000 T _Z9my_plugini

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

 func = dlsym(handle, "_Z9my_plugini");

传统上,不同的编译器可能会以不同的方式修改名称,因此这可能非常脆弱,尽管如今大多数 C++ 编译器都会同意在给定平台上使用标准方式修改名称。

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

于 2013-08-07T07:10:24.003 回答
1

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

于 2013-08-07T08:48:29.287 回答
0

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

extern "C" {

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

}

通常extern "C" {,右大括号}被包裹在宏中,这些宏以__cplusplus内置宏为条件,因此也可以从纯 C 中使用标头。这也封装了您认为令人反感的部分。

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

于 2013-08-07T07:26:32.120 回答