C++动态链接库和void指针

C++ dynamically linked library and void pointer

我处于以下情况:我正在编写一个必须动态加载 C++ 库的 C++ 程序(即通过 dlopen 和 Linux 和 LoadLibrary 中的朋友和 Windows 中的朋友)。这可以通过创建 C 接口来完成。

现在,在程序和库中我管理一些 object,其中有一些指定的模板成员和一些方法:

struct MyObject {
    std::vector<int> _vec;
    //...
    void do_something();
};

现在,如果库是静态加载的,我会编写一个库函数,例如

void some_function(MyObject& o);

但由于它是动态加载的,所以我需要一些其他签名。我在想以下内容:一个常见的 header like

//interface.hpp
extern "C" {
    void ob_w(void*);
}


struct MyObject {
   //...
}

然后,图书馆那边

//lib.cpp
#include "interface.hpp"

void ob_w(void* ptr)
{
    MyObject* p = (MyObject*)ptr;

    p->do_something();
}

并且,对于主程序

//main.cpp
#include "interface.hpp"

int main()
{
    void* handle = nullptr;
    void (*fptr)(void*);

    handle = dlopen(...)
    fptr = dlsym(...)

    MyObject foo;
    fptr((void*)&foo);

    //...
}

环顾四周,我发现了其他类似的问题,但在所有这些问题中,库都是用 C 编写的,因此采用了不同的解决方案。这里库和程序都是用 C++ 编写的,void 指针只是为了避免一些适配器。 我想知道我的方法是否正确(我在linux机器上试过,似乎给出了正确的结果)和安全.如果不是,我如何在不引入任何开销的情况下传递 object 的指针(例如某些适配器)?

将我的评论提升为答案:如果您愿意使用 C++,则绝对不需要更改函数的签名以使其与动态链接一起使用。即以下作品:

extern "C" void some_function(MyObject& o) {
    o.do_something();
}

然后你可以得到一个 main.cpp 如下(片段):

void* lib = dlopen("myobject.so", RTLD_LAZY);
if (not lib)  fail_spectacularly();

void (*some_function)(MyObject&) = reinterpret_cast<decltype(some_function)>(dlsym(lib, "some_function"));
if (not some_function) fail_spectacularly();

MyObject obj = whatever;
some_function(obj);