I only have 1 .so file from old project. How can I use this file without creating the same package in project or module ?
Asked
Active
Viewed 783 times
1
-
You might be able to change it using a hex editor or some similar tool. But it seems much easier to just create a package with the same name within your new project. – Michael Feb 20 '19 at 09:22
-
Hi @Michael I tried using notepad ++ to edit the hex text of the file compared to another package (I changed 1 word for test) but there was an error: "java.lang.UnsatisfiedLinkError: No implementation found for com void ...." – mdtuyen Feb 20 '19 at 09:35
-
That's not enough information. You should show exactly what you changed, and the full exact error messages that you get. – Michael Feb 20 '19 at 09:38
-
@Michael Example old package of so file is: "com.abc.def" I find in hex editor to change "f" to "e" then package change to "com.abc.dee". Messenges show "No implementation found for void com.abc.dee.Native.appInit(java.lang.String, java.lang.String, int, boolean) (tried Java_com_abc_dee_Native_appInit and Java_com_abc_dee_Native_appInit__Ljava_lang_String_2Ljava_lang_String_2IZ)" – mdtuyen Feb 20 '19 at 09:46
-
Not only the method name, but the method signature need to match exactly with the one inside .so. Also, you need to change all the occurrences of that JNI method. – shizhen Feb 21 '19 at 05:10
1 Answers
3
Actually, you don't need to change function name in .so
file. You can use dlopen
to load your .so
library dynamically at runtime and dlsym
to get pointer for you YOUR_FUNCTION_NAME()
and then call YOUR_FUNCTION_NAME()
by pointer. For do that in your current project you can create "wrapper" like that:
public class OldSoHelper {
public static native void loadOldSo();
public static native <TYPE_OF_RESULT> runFunFromOldSo(<PARAMETERS>);
public static native void unloadOldSo();
}
and in corresponding .c/.cpp
file of current project (e.g. native-lib.cpp
by default):
void *handle;
<TYPE_OF_OLD_FUNCTION> (*old_fun_wrapper)(<PARAMETERS_OF_OLD_FUNCTION>);
extern "C"
JNIEXPORT void JNICALL
Java_<YOUR_PACKAGE_NAME>_OldSoHelper_loadOldSo(JNIEnv *env, jclass type) {
handle = dlopen("<YOUR_OLD_SO>.so", RTLD_NOW);
old_fun_wrapper = (<TYPE_OF_OLD_FUNCTION> (*)(<PARAMETERS_OF_OLD_FUNCTION>))(dlsym(handle, "<OLD_FUNCTION_NAME_e.g._Java_com_abc_dee_Native_appInit>"));
}
extern "C"
JNIEXPORT jobject JNICALL
Java_<YOUR_PACKAGE_NAME>_OldSoHelper_runFunFromOldSo(JNIEnv *env, jclass type,
<PARAMETERS_FOR_OLD_FUNCTION>)
{
jclass ResultClass = env->FindClass("YOUR/PACKAGE/NAME/RESULT_CLASS");
jobject result = ...
jfieldID fieldId = env->GetFieldID(ResultClass, "<FIELD_NAME>", "<FILED_TYPE_LETTER>");
<TYPE_OF_OLD_FUNCTION> res = old_fun_wrapper(<PARAMETERS_FOR_OLD_FUNCTION>);
env->Set<TYPE>Field(result, fieldId , res.filed);
return result;
}
extern "C"
JNIEXPORT void JNICALL
Java_<YOUR_PACKAGE_NAME>_OldSoHelper_unloadOldSo(JNIEnv *env, jclass type) {
if (handle) {
dlclose(handle);
}
}
and from java code you can call:
...
// when you need old .so e.g. in onCreate()
OldSoHelper.loadOldSo();
...
// when you no need to call function from old .so
<TYPE_OF_RESULT> result = OldSoHelper.runFunFromOldSo(<PARAMETERS>);
...
// when you no need old .so e.g. in onDestroy()
OldSoHelper.unloadOldSo();
...

Andrii Omelchenko
- 13,183
- 12
- 43
- 79