0

I'm using the following bootstrapping code to load my native activity (jngl-test):

#include <android/native_activity.h>
#include <android/log.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdexcept>

const std::string LIB_PATH = "/data/data/com.bixense.jngl_test/lib/";

void* load_lib(const std::string& l) {
    void* handle = dlopen(l.c_str(), RTLD_NOW | RTLD_GLOBAL);
    if (!handle) {
        throw std::runtime_error(std::string("dlopen(") + l + "): " + strerror(errno));
    }
    return handle;
}

void ANativeActivity_onCreate(ANativeActivity* app, void* ud, size_t udsize) {
    try {
        load_lib(LIB_PATH + "libogg.so");
        load_lib(LIB_PATH + "libvorbis.so");
        auto main = reinterpret_cast<void (*)(ANativeActivity*, void*, size_t)>(
            dlsym(load_lib(LIB_PATH + "libjngl-test.so"), "ANativeActivity_onCreate")
        );
        if (!main) {
            throw std::runtime_error("undefined symbol ANativeActivity_onCreate");
        }
        main(app, ud, udsize);
    } catch(std::exception& e) {
        __android_log_print(ANDROID_LOG_ERROR, "bootstrap", e.what());
        ANativeActivity_finish(app);
    }
}

I get the following error message:

dlopen(/data/data/com.bixense.jngl_test/lib/libjngl-test.so): Invalid argument

This doesn't tell me at all whats going wrong. Is there a way to get more debug output? What could "Invalid argument" mean?

jhasse
  • 2,379
  • 1
  • 30
  • 40

2 Answers2

0

I fixed it:

dlerror()

gives a far better error message.

Here's the bootstrap code if someone is interested:

#include <android/native_activity.h>
#include <android/log.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdexcept>

void* load_lib(const std::string& l) {
    auto handle = dlopen(std::string("/data/data/com.bixense.jngl_test/lib/" + l).c_str(),
                         RTLD_NOW | RTLD_GLOBAL);
    if (!handle) {
        throw std::runtime_error(std::string("dlopen(") + l + "): " + dlerror());
    }
    return handle;
}

void ANativeActivity_onCreate(ANativeActivity* app, void* ud, size_t udsize) {
    try {
        load_lib("libogg.so");
        load_lib("libvorbis.so");
        auto main = reinterpret_cast<void (*)(ANativeActivity*, void*, size_t)>(
            dlsym(load_lib("libjngl-test.so"), "ANativeActivity_onCreate")
        );
        if (!main) {
            throw std::runtime_error("undefined symbol ANativeActivity_onCreate");
        }
        main(app, ud, udsize);
    } catch(std::exception& e) {
        __android_log_print(ANDROID_LOG_ERROR, "bootstrap", e.what());
        ANativeActivity_finish(app);
    }
}
jhasse
  • 2,379
  • 1
  • 30
  • 40
-1

You could do this..
put that lib in raw directory and load it
For raw files, you should consider creating a raw folder inside res directory and then call

 getResources().openRawResource(resourceName) 

from your activity.
then you can use it the way you like.

blganesh101
  • 3,647
  • 1
  • 24
  • 44
  • because you cannot access /data/data directly like this – blganesh101 Jun 06 '13 at 18:50
  • I can, got the code from http://stackoverflow.com/questions/12524664/cant-load-native-shared-library-with-dependencies-in-a-native-activity-app?rq=1 and it works fine for libogg.so and libvorbis.so. – jhasse Jun 06 '13 at 19:15
  • It's not so much "you cannot" as "you should not". The full path to the app-specific directory is not guaranteed to be the same across all versions of Android. You probably ought to start with `Context.getFilesDir()` if `LD_LIBRARY_PATH` doesn't cover it. – fadden Jun 07 '13 at 20:07
  • dlopen will treat the path as absolute if it contains a / if you need to set this to the /data/data dir then its best to get this path using JNI thats sure to give you the correct path – gheese Nov 08 '13 at 18:58