Download

Loading third party libraries w/ dlopen

I am developing a plugin which integrates a third party library with unreal for Android. The setup is as follows:
I have a .jar library which contains java functions that i call via JNI and AndroidThunk methods defined in a UPL file like this:


<root xmlns:android="http://schemas.android.com/apk/res/android">

<proguardAdditions>
<insert>
-dontwarn com.example.**
-keep class com.example.** {*;}
</insert>
</proguardAdditions>

<resourceCopies>

<copyFile src="$S(PluginDir)/../ThirdParty/TTSLibrary/Android/libs/myclass.jar" dst="$S(BuildDir)/libs/myclass.jar" />
<copyDir src="$S(PluginDir)/../ThirdParty/TTSLibrary/Android/armeabi-v7a" dst="$S(BuildDir)/libs/armeabi-v7a" />

</resourceCopies>

<gameActivityImportAdditions>
<insert>
import com.example.MyClass;
</insert>
</gameActivityImportAdditions>

<gameActivityClassAdditions>
<insert>

public void AndroidThunkJava_Init(){
MyClass myClass = new MyClass();
myClass.load();
}
</insert>
</gameActivityClassAdditions>
</root>

The java library requires a couple of different native .so libraries that is loaded during runtime. This part is a two step process, in the first step the first set of native libraries. I have checked that this set of libraries are being loaded properly and they are. For the second step, the remaining native libraries are to be loaded. This is where I encounter some troubles. I’m certain that the libraries are being copied to the correct destination via the UPL file as I successfully load some of them. However, when i add another native library, lets call it “libmylib_a.so” that is loaded after the first set of native libraries are loaded, I encounter some trouble.

By adding the native library libmylib_a.so to the libs folder, my game immediately crashes on startup giving me the following error message:



java.lang.UnsatisfiedLinkError: dlopen failed: library "libmylib.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1657)
at com.epicgames.ue4.GameActivity.<clinit>(GameActivity.java:6211)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1180)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2829)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

On further inspection i noticed that the ELF-header of libmylib_a.so contained a SONAME different from the name of the file. The SONAME was: “libmylib.so”. I read somewhere that having the SONAME and filename differ could cause troubles with dlopen. So i changed the SONAME using patchelf to match the file name itself. Now my game does not crash on startup, but i instead get the error:


libmylib_a.so [dlopen failed: library "libmylib_a.so" not found]

during runtime when the library is to be loaded. I do not have access to the source code of any of the native libraries nor the java library, so changing anything there is out of the question.

Could it be because I modified the ELF header? If so, how would I circumvent having my game crash on startup due to it trying to load the native library with the filename differing from the SONAME?

I have now solved this. I struggled with the first error for quite a while, probably because there was some dependency and the libraries being loaded in the wrong order. I fixed it by adding this to my UPL file


 <gameActivityClassAdditions>
<insert>
static
{
System.loadLibrary("mylib_a");
}
</insert>
</gameActivityClassAdditions>


The second error was most likely caused by something unrelated and the thirdparty library I was using was outputting an incorrect error message.