直接从Android NDK中的C ++代码调用另一个.so文件中的函数

时间:2015-05-21 08:12:31

标签: android c++ android-ndk java-native-interface

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

2 个答案:

答案 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