我a.so
定义void a()
和b.so
,定义void b()
。它们都放在.apk中,因此可供Android应用程序使用。
现在假设我通过JNI呼叫a()
。是否可以在完全绕过JNI的同时从b()
拨打a()
?
我可以在Android中这样做吗(代码仅用于说明,因此可能有一些错误)?
void a() {
void *handle = dlopen("b.so", RTLD_LAZY);
void (*b)() = dlsym(handle, "b");
b();
}
我是否需要添加完全限定的路径,或b.so
已添加到应用的LD_LIBRARY_PATH
?
答案 0 :(得分:1)
你可以在Android上这样做,但要注意共享库放在Android文件夹中的位置。它可以从版本更改为另一个版本。 例如,在api 17上,它保留在/ data / app-lib /中。你可以硬写它,但最好的是调用Java(通过JNI)来知道库应该在哪里。 我们在项目中做了类似的事情:
JNIEnv* env;
const char* temp;
jobject oActivity = state->activity->clazz;
jclass cActivity = env->GetObjectClass(oActivity);
// get the path to where android extracts native libraries to
jmethodID midActivityGetApplicationInfo = env->GetMethodID(cActivity, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
jobject oApplicationInfo = env->CallObjectMethod(oActivity, midActivityGetApplicationInfo);
jclass cApplicationInfo = env->GetObjectClass(oApplicationInfo);
jfieldID fidApplicationInfoNativeLibraryDir = env->GetFieldID(cApplicationInfo, "nativeLibraryDir", "Ljava/lang/String;");
jstring sNativeLibraryDir = (jstring)env->GetObjectField(oApplicationInfo, fidApplicationInfoNativeLibraryDir);
temp = env->GetStringUTFChars(sNativeLibraryDir, NULL);
strcpy(libpath, temp);
strcat(libpath, "/");
然后你在战斗中推动你的dlopen + dlsym组合它应该有用。
答案 1 :(得分:0)
如上所述:How do I load a shared object in C++?
在C ++中有两种加载共享对象的方法
对于这些方法中的任何一种,您始终需要要使用的对象的头文件。标题将包含您要在代码中使用的类或对象的定义。
#include "blah.h"
int main()
{
ClassFromBlah a;
a.DoSomething();
}
gcc yourfile.cpp -lblah
动态(在Linux中):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("libm.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
return 0;
}
PS:对于动态方法,它取决于平台:在Linux上,您使用dlopen,在Windows上,您使用LoadLibrary。