Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何动态加载和调用具有库特定类型作为函数参数的符号_C++_Linux_Fuse_Dlopen_Dlsym - Fatal编程技术网

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

C++ 如何动态加载和调用具有库特定类型作为函数参数的符号,c++,linux,fuse,dlopen,dlsym,C++,Linux,Fuse,Dlopen,Dlsym,假设我有以下几点: // lib1.h struct S { int x; }; void f(S* s); // defined in .cpp 及 导致lib1.so和lib2.so 所以,我的问题是: #include <dlfcn.h> int main() { const auto lib_to_use = <some application level logic, resulting in lib1.so or lib2.so>;

假设我有以下几点:

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

导致
lib1.so
lib2.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);
}
#包括
int main()
{
const auto lib_to_use=;
const auto lib=dlopen(lib-to-use,RTLD-LAZY);
断言(lib);
常量自动函数=dlsym(lib,“f”);
断言(func);
//考虑到需要不同的、特定于库的类型“S”,如何调用“func”?
dlclose(lib);
}

我的现实世界问题是-如何在运行时加载
libfuse2
libfuse3
并执行
fuse\u main\u real
,因为它具有
fuse\u操作*
参数,这是一个带有函数指针的
结构,但两个版本的类型不同


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

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

答案是保持这些定义的独立性:将每个动态对象包装在自己的一个对象中(通过简单的
-l
链接),该对象公开了一个公共接口(该问题必须有可能有意义)。加载主程序中的一个或另一个,并使用该接口中的唯一类型调用它

鉴于使用不同的库特定类型
S
,如何调用
func

显然,您的主程序中不能同时有与
lib1
S
lib2
S
匹配的类型
S
。因此您必须声明两个单独的类型:
S1
S2

其余的都是无关紧要的:

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);
}

这些结构真的有完全相同的名称吗?然后你会破坏。是的,它们有。但我不知道这是如何破坏ODR的,它们永远不会同时被加载?我的意思是,只会加载其中一个。(我甚至不确定这是否会破坏ODR,因为使用了
dlsym
,而不仅仅是自动动态链接)至于这些库,它们是相关的吗?它们是“你的”库吗(也就是说,你可以随意编辑它们)?那么为什么不对结构使用继承呢?@Someprogrammerdude它们不是,我已经写了我的真实案例-它们是
libfuse
(不兼容,但在同一台机器上设计共存)当您已经有两个答案时设置赏金似乎很奇怪。如果您对目前的答案不满意,您可能应该说明原因。这是未定义的行为,因为函数是通过错误类型的函数指针调用的。(无论如何,它肯定有效。)不知道为什么这里会有反对票,我很好奇这背后的原因是什么。有人吗?因为这正是我认为我应该做的,以解决这个限制,所以+1。我会等待,看看是否会出现更好的答案(不使用这种解决方法)。
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);
}