【问题标题】:C++ dynamically linked library and void pointerC++动态链接库和空指针
【发布时间】:2022-01-22 18:37:56
【问题描述】:

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

现在,无论是在程序中还是在库中,我都管理着一些具有一些指定模板成员和一些方法的对象:

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

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

void some_function(MyObject& o);

但由于它是动态加载的,我需要一些其他签名。我在想以下几点:一个常见的标题,如

//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 机器上尝试过,似乎给出了正确的结果)和 安全。如果不是,我如何在不引入任何开销(例如某些适配器)的情况下传递对象的指针?

【问题讨论】:

  • 使用 C++ vector 作为 DLL 的参数只是糟糕的 API 设计。您应该努力使其平台和语言独立。如果您希望使用 C++ 容器,请将它们保留在 DLL 内部。如果您不想要开销,请不要使用 C++ 标准库。
  • 可以在动态链接库的签名中使用 C++ 类型就好了。理论上你没有 ABI 稳定性,但实际上这不是问题(尤其是当你同时控制库和消费者时)。
  • @Lundin vector 只是一个例子。在我的真实代码中没有vector,而是我自己定义的另一个模板。这只是一个减少行数的例子。
  • @KonradRudolph 它违背了使用 DLL 的全部目的。如果您仍然强制执行特定语言和 ABI,为什么不静态链接它?
  • @Lundin 这些并不是使用 DLL 的唯一原因。我认为,它们甚至不是主要原因。其他原因包括制作插件架构或其他不希望使用静态链接的场景。在开发 ld.so 时,对其他语言的考虑充其量只是事后的想法。这可能在 Windows 上会有所不同,不知道。

标签: c++ c dll dlopen


【解决方案1】:

将我的评论提升为答案:如果您愿意使用 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);

【讨论】:

    猜你喜欢
    • 2012-09-22
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多