i have an android app which spawns many native executables dinamically linked with libraries i distribute with the package. To launch those binaries, i use the LD_LIBRARY_PATH e
Here is a simple wrapper I wrote about:
#include
#include
#include
#include
typedef int (*main_t)(int argc, char** argv);
static int help(const char* argv0)
{
printf("%s: simple wrapper to work around LD_LIBRARY_PATH\n\n", argv0);
printf("Args: executable, list all the libraries you need to load in dependency order, executable again, optional parameters\n");
printf("example: %s /data/local/ttte /data/data/app/com.testwrapper/lib/ttt.so /data/local/ttte 12345\n", argv0);
printf("Note: the executable should be built with CFLAGS=\"-fPIC -pie\", LDFLAGS=\"-rdynamic\"\n");
return -1;
}
int main(int argc, char** argv)
{
int rc, nlibs;
void *dl_handle;
if (argc < 2)
{
return help(argv[0]);
}
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "running '%s'", argv[1]);
for (nlibs = 2; ; nlibs++)
{
if (nlibs >= argc)
{
return help(argv[0]);
}
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "loading '%s'", argv[nlibs]);
dl_handle = dlopen(argv[nlibs], 0); // do not keep the handle, except for the last
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "loaded '%s' -> %p", argv[nlibs], dl_handle);
if (strcmp(argv[1], argv[nlibs]) == 0)
{
break;
}
}
main_t pmain = (main_t)dlsym(dl_handle, "main");
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "found '%s' -> %p", "main", pmain);
rc = pmain(argc - nlibs, argv + nlibs);
// we are exiting the process anyway, don't need to clean the handles actually
// __android_log_print(3, "wrapper", "closing '%s'", argv[1]);
// dlclose(dl_handle);
return 0;
}
To keep it readable, I drop most of error handling, unessential cleanup, and handling of special cases.
Android.mk
for this executable:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := wrapper
LOCAL_SRC_FILES := wrapper/main.c
LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE)
Note that you must take care of deployment: packaging this wrapper
into the APK, extraction to some local path (never to USB storage or to /sdcard
!), marking it as executable (chmod 777
).
These are the additional parameters you must supply when you build the executables you run through the wrapper
. If you use ndk-build
to build them, it looks as follows:
LOCAL_C_FLAGS += -fPIC -pie
LOCAL_LDFLAGS += -rdynamic
Note that you don't need to chmod
for these executables anymore. Another trick: you can build the secondary executables into shared libraries, and the same wrapper will continue to work! This saves the trouble of deployment of these binaries. NDK and Android build will deliver them safely through libs/armeabi of the APK to your app's lib directory automagically.
Update
There seems to be a much easier solution, using the ProcessBuilder with modified environment: https://stackoverflow.com/a/8962189/192373.