如何动态加载和调用具有库特定类型作为函数参数的符号

问题描述 投票:2回答:1

假设我有以下内容:

// lib1.h
struct S 
{
    int x;
};
void f(S* s);  // defined in .cpp

// lib2.h
struct S 
{
    int x;
    int y;
};
void f(S* s);  // defined in .cpp

产生lib1.solib2.so

所以,我的问题是:

#include <dlfcn.h>

int main()
{
    const auto lib_to_use = <some application level logic, resulting in lib1.so or lib2.so>;
    const auto lib = dlopen(lib_to_use, RTLD_LAZY);
    assert(lib);

    const auto func = dlsym(lib, "f");
    assert(func);

    // how do I call `func`, given the fact it takes different, library-specific type `S`?

    dlclose(lib);
}

我的现实世界中的问题是-如何在运行时加载libfuse2libfuse3并执行fuse_main_real,给定它具有fuse_operations*参数,即struct带有函数指针,但两个版本的类型不同?

Edit:我不认为这会违反一定义规则-只有其中一个会同时链接,而不会两个都链接。 (我也不确定是否同时加载了ODR,因为它们都是手动使用的,但这是另一个主题)

c++ linux fuse dlopen dlsym
1个回答
0
投票

鉴于具有不同库特定类型func的事实,我怎么称呼S

显然,您的主程序中不能同时输入S lib1S lib2的类型S。因此,您必须声明两个单独的类型:S1S2

其余的都很简单:

int version = which_version_should_I_use();
if (version == V1) {
  void *h = dlopen("lib1.so", RTLD_LAZY);
  void (*fn)(S1*) = (void (*)(S1*))dlsym(h, "f");
  assert(fn != NULL);
  S1 s = ...;
  fn(&s);
} else {
  // must be V2
  void *h = dlopen("lib2.so", RTLD_LAZY);
  void (*fn)(S2*) = (void (*)(S2*))dlsym(h, "f");
  assert(fn != NULL);
  S2 s = ...;
  fn(&s);
}

-1
投票

在某种程度上可以说该标准适用于动态对象,您说对了,永远不会加载在一起的多个对象之间没有ODR冲突(因为没有包含两个定义的program)。如果它包含(显然)每种类类型的定义或包含一个类的定义,并且(在运行时选择是它)加载使用另一种类型的动态对象,则不能对您的程序说同样的话。 (使用DLL的情况更奇怪:共享类型,但不共享其成员函数,静态数据成员或RTTI符号。)

答案是将这些定义分开:wrap每个动态对象都属于您自己(通过简单的-l与之链接),它公开了一个[[common interface(对于这个问题才有意义)。在主程序中加载those中的一个,然后使用该接口中唯一的类型#include d进行调用。

© www.soinside.com 2019 - 2024. All rights reserved.