C++ 如何在 C++ 中使用 dlopen()?
C++ How to use dlopen() in c++?
我正在尝试在我的包中使用预构建的 tensorflow c-api
和 cpp-wrapper
。不幸的是我遇到了段错误。搜索后我发现有一个 Git Issue about it: Linking to both tensorflow and protobuf causes segmentation fault during static initializers.
所以我可以通过以下方式解决问题:
The workarounds sound like (1) only load the second copy of protobuf in a .so that does not use TensorFlow, and you can use both that .so and TensorFlow's .so from your main program, (2) instead of linking normally, dlopen() TensorFlow with RTLD_DEEPBIND set so TensorFlow prefers its own symbols.
我想尝试使用 dlopen() 加载库,不幸的是我从未使用过它,而且找不到一个很好的使用示例。在我的案例中我将如何使用它?
我的初步理解:
将它加载到我的 cpp-wrapper 的 header 中,因为他们使用 tensorflow functions/header?
但是我真的需要更改 cpp-wrapper header 的每个函数并引用加载的处理程序吗?
一点dlopen
例子:
一些用C写的lib,我们称之为foobar.so
#include <stdio.h>
void foo() { printf("foo\n"); }
void bar() { printf("bar\n"); }
gcc -o foobar.so foobar.c -shared -fPIC
C++ 中的 (foobar) 包装器
#include <dlfcn.h>
struct FooBar {
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
FooBar() {
//probably best not in the constructor, but we're lazy (for now)
//and of course no error checking (so don't)
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
}
~FooBar() {
dlclose(foobar_lib);
}
};
int main()
{
FooBar foobar;
foobar.foo();
foobar.bar();
return 0;
}
或
#include <dlfcn.h>
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
int main()
{
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
foo();
bar();
dlclose(foobar_lib);
return 0;
}
g++ -ldl -o foobar_test foobar_test.cpp
对于您从原始库中使用的每个符号,您必须调用 dlsym
来获取其地址。
所以是的,这是一项乏味的工作,因为您要实现一个包装器来提供底层库的全部功能。
例如,opengl 开发人员非常清楚这意味着什么。幸运的是,多年来,现在有许多可用的工具,这有助于在运行时以 no/less 的努力加载无数的符号。也许有类似tensorflow的东西。
我正在尝试在我的包中使用预构建的 tensorflow c-api
和 cpp-wrapper
。不幸的是我遇到了段错误。搜索后我发现有一个 Git Issue about it: Linking to both tensorflow and protobuf causes segmentation fault during static initializers.
所以我可以通过以下方式解决问题:
The workarounds sound like (1) only load the second copy of protobuf in a .so that does not use TensorFlow, and you can use both that .so and TensorFlow's .so from your main program, (2) instead of linking normally, dlopen() TensorFlow with RTLD_DEEPBIND set so TensorFlow prefers its own symbols.
我想尝试使用 dlopen() 加载库,不幸的是我从未使用过它,而且找不到一个很好的使用示例。在我的案例中我将如何使用它?
我的初步理解: 将它加载到我的 cpp-wrapper 的 header 中,因为他们使用 tensorflow functions/header? 但是我真的需要更改 cpp-wrapper header 的每个函数并引用加载的处理程序吗?
一点dlopen
例子:
一些用C写的lib,我们称之为foobar.so
#include <stdio.h>
void foo() { printf("foo\n"); }
void bar() { printf("bar\n"); }
gcc -o foobar.so foobar.c -shared -fPIC
C++ 中的 (foobar) 包装器
#include <dlfcn.h>
struct FooBar {
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
FooBar() {
//probably best not in the constructor, but we're lazy (for now)
//and of course no error checking (so don't)
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
}
~FooBar() {
dlclose(foobar_lib);
}
};
int main()
{
FooBar foobar;
foobar.foo();
foobar.bar();
return 0;
}
或
#include <dlfcn.h>
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
int main()
{
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
foo();
bar();
dlclose(foobar_lib);
return 0;
}
g++ -ldl -o foobar_test foobar_test.cpp
对于您从原始库中使用的每个符号,您必须调用 dlsym
来获取其地址。
所以是的,这是一项乏味的工作,因为您要实现一个包装器来提供底层库的全部功能。
例如,opengl 开发人员非常清楚这意味着什么。幸运的是,多年来,现在有许多可用的工具,这有助于在运行时以 no/less 的努力加载无数的符号。也许有类似tensorflow的东西。