sashoalm
sashoalm

Reputation: 79645

Directly call function in another .so file from C++ code in Android NDK

I have a.so which defines void a() and b.so which defines void b(). They are both put in the .apk so they are available to the Android application.

Now suppose that I'm calling a() through JNI. Is it possible to call b() from a() while completely bypassing JNI?

Can I do it this way in Android (the code is only for illustration, so it might have some errors)?

void a() {
    void *handle = dlopen("b.so", RTLD_LAZY);
    void (*b)() = dlsym(handle, "b");
    b();
}

Would I need to add the fully qualified path, or is b.so already in LD_LIBRARY_PATH for the app?

Upvotes: 3

Views: 3391

Answers (2)

brainsandwich
brainsandwich

Reputation: 492

You can do it this way on Android, though take care of where the shared library has been put in Android folders. It can change from a version to another. On api 17 for example, it remains in /data/app-lib/. You can hardwrite it, but the best is to make calls to Java (through JNI) to know where the libraries should be. We're doing something like this in our project :

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, "/");

Then you push your dlopen + dlsym combo in the fight and it should work.

Upvotes: 1

Fouad Wahabi
Fouad Wahabi

Reputation: 804

As mentioned here : How do I load a shared object in C++?

There are two ways of loading shared objects in C++

For either of these methods you would always need the header file for the object you want to use. The header will contain the definitions of the classes or objects you want to use in your code.

#include "blah.h"
int main()
{
  ClassFromBlah a;
  a.DoSomething();
}

gcc yourfile.cpp -lblah

Dynamically (In 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 : for the dynamic approach, it depends on platform : on Linux, you use dlopen, on windows, you use LoadLibrary.

Upvotes: 0

Related Questions