在 C++ 程序中如何调用动态库 (.so) 中的 C++ class 的构造函数
In C++ program how to call a constructor of C++ class which in dynamic library(.so)
我可以调用动态库(.so)中的C++常用函数class,但不知道如何调用动态库(.so)中的C++class构造函数。所以)。
JNIEXPORT jint JNICALL Java_com_example_hellobreakdd_MainActivity_helloBreak (JNIEnv *, jobject){
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libtest.so", RTLD_NOW);
if (!handle) {
__android_log_print(ANDROID_LOG_ERROR, "start", dlerror());
}
*(void **) (&cosine) = dlsym(handle, "Add");
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
return 1;
}
class 的构造函数在您初始化 class 的实例并因此创建对象时被调用,
MyClass MyInstance(param);
假设MyClass
是一个class,param
是要传递给构造函数的参数,这将调用构造函数或MyClass
无法调用构造函数manually/directly。所以你必须在你的共享对象中创建一个对象,如下所示,
class shape {
public:
void draw();
};
extern "C" {
Shape *maker(){
return new Shape();
}
在这种情况下,您需要一个 class 形状的头文件来从 void 指针进行类型转换。说,
void *mkr = dlsym(hndl, "maker"); // get maker method symbol
shape *my_shape = static_cast<shape *()>(mkr)(); //get the shape object
如果您不想调用基于 C 的函数,那么您必须找到损坏的名称并使用它来调用 maker() 函数并避免 "extern c"。在这种情况下,您可以使用 nm 命令获取 .so 文件中的符号。
而是在共享对象中创建一个全局对象,并使用上述方法获取对象实例。在这种情况下,当您使用 dlopen() 打开共享对象时,将调用构造函数。
希望这对您的问题有所帮助。
万一修改 .so 不是一个选项。我们可以通过相应地调用new和构造函数从.so手动创建一个c++ class的对象。
通常,编译器会完成这种工作,但我们可以通过一些内联汇编代码来完成。
这是在 x86 代码中创建虚拟 class 对象的示例:
asm volatile {
"mov , %%edi\n"
"callq *%2\n"
"mov %%rax, %%rbx\n"
"mov %%rbx, %%rdi\n"
"callq *%1\n"
"mov %%rbx, %0\n"
: =m "my_pointer"
: m "dummy_new", m "dummy_constructor"
: "%edi", "%rax", "%rbx", "%rdi"
}
我可以调用动态库(.so)中的C++常用函数class,但不知道如何调用动态库(.so)中的C++class构造函数。所以)。
JNIEXPORT jint JNICALL Java_com_example_hellobreakdd_MainActivity_helloBreak (JNIEnv *, jobject){
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libtest.so", RTLD_NOW);
if (!handle) {
__android_log_print(ANDROID_LOG_ERROR, "start", dlerror());
}
*(void **) (&cosine) = dlsym(handle, "Add");
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
return 1;
}
class 的构造函数在您初始化 class 的实例并因此创建对象时被调用,
MyClass MyInstance(param);
假设MyClass
是一个class,param
是要传递给构造函数的参数,这将调用构造函数或MyClass
无法调用构造函数manually/directly。所以你必须在你的共享对象中创建一个对象,如下所示,
class shape {
public:
void draw();
};
extern "C" {
Shape *maker(){
return new Shape();
}
在这种情况下,您需要一个 class 形状的头文件来从 void 指针进行类型转换。说,
void *mkr = dlsym(hndl, "maker"); // get maker method symbol
shape *my_shape = static_cast<shape *()>(mkr)(); //get the shape object
如果您不想调用基于 C 的函数,那么您必须找到损坏的名称并使用它来调用 maker() 函数并避免 "extern c"。在这种情况下,您可以使用 nm 命令获取 .so 文件中的符号。
而是在共享对象中创建一个全局对象,并使用上述方法获取对象实例。在这种情况下,当您使用 dlopen() 打开共享对象时,将调用构造函数。
希望这对您的问题有所帮助。
万一修改 .so 不是一个选项。我们可以通过相应地调用new和构造函数从.so手动创建一个c++ class的对象。
通常,编译器会完成这种工作,但我们可以通过一些内联汇编代码来完成。
这是在 x86 代码中创建虚拟 class 对象的示例:
asm volatile {
"mov , %%edi\n"
"callq *%2\n"
"mov %%rax, %%rbx\n"
"mov %%rbx, %%rdi\n"
"callq *%1\n"
"mov %%rbx, %0\n"
: =m "my_pointer"
: m "dummy_new", m "dummy_constructor"
: "%edi", "%rax", "%rbx", "%rdi"
}