- WebRTC app - C# / Xamarin - Part #1 - Building platform native webrtc library
- WebRTC app - C# / Xamarin - Part #2 - Attempt #1 - failure to using a JNI .so file directly from C# / Mono
- WebRTC app - C# / Xamarin - Part #2 - Attempt #2 - success using a JNI .so file from C# / Mono
- WebRTC app - C# / Xamarin - (C# - JNI - C/C++) - Summary and GitHub repository
In my previous posting WebRTC app - C# / Xamarin - Part #1 - Building platform native webrtc library I have showed how to build a native library that we need to use to build a WebRTC app on Xamarin / Mono.Droid.
In this posting I will take you through my struggles, subsequent failure and the next posting finally success on how to actually use this JNI native library from Mono.Android.
I started a new solution in Visual Studio 2013 and added new Android Application project. Then according to Xamarin: Using Native Libraries.
I needed to add my .so file to the location
<project>\lib\armeabi-v7a\libwebrtc-video-demo-jni.so.
The next step that I tried was to start using DllImport statements.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using System.Runtime.InteropServices; using Android.Content; using Android.Util; using Encoding = System.Text.Encoding; namespace WebRtc { public class ViEAndroidJavaAPI { ... // API Native [DllImport( "libwebrtc-video-demo-jni.so" )] private static extern bool NativeInit(Context context); // Video Engine API // Initialization and Termination functions [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int GetVideoEngine(); [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int Init( bool enableTrace); [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int Terminate(); ... |
Trying to run my project yielded some EntryPointNotFoundException in the error log. After a bit of Google-ing I found that the method names as seen from Mono are not as you expect instead they contain the full package/class path.
Using the following command on the Ubuntu build machine
1 | ~ /WebRTCDemo/trunk/webrtc/video_engine/test/android/libs/armeabi-v7a $ arm-linux-androideabi-nm -D libwebrtc-video-demo-jni.so |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 00015358 T JNI_OnLoad 00015be4 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_AddRemoteRenderer 00016e3c T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_CreateChannel 00015f14 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_EnableNACK 00015f58 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_EnablePLI 00015e04 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetCameraOrientation 00015acc T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetCodecs 000153d4 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetVideoEngine 000154cc T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_Init 000153d0 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_NativeInit 00015c30 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_RemoveRemoteRenderer 00015fb0 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetCallback 00015ea8 T Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetExternalMediaCodecDecoderRenderer ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | using System; using System.Runtime.InteropServices; using Android.Content; using Android.Util; using Encoding = System.Text.Encoding; namespace WebRtc { public class ViEAndroidJavaAPI { ... // API Native [DllImport( "libwebrtc-video-demo-jni.so" )] private static extern bool Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_NativeInit(Context context); // Video Engine API // Initialization and Termination functions [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetVideoEngine(); [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_Init( bool enableTrace); [DllImport( "libwebrtc-video-demo-jni.so" )] public static extern int Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_Terminate(); ... |
UNHANDLED EXCEPTION: System.Runtime.InteropServices.MarshalDirectiveException: Type Java.Lang.Object which is passed to unmanaged code must have a StructLayout attribute.
1 2 3 4 5 6 7 | 12-21 19:29:04.298 I/MonoDroid(15226): UNHANDLED EXCEPTION: System.Runtime.InteropServices.MarshalDirectiveException: Type Java.Lang.Object which is passed to unmanaged code must have a StructLayout attribute. 12-21 19:29:04.298 I/MonoDroid(15226): at (wrapper managed-to-native) WebRtc.ViEAndroidJavaAPI.Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_NativeInit (Android.Content.Context) 12-21 19:29:04.298 I/MonoDroid(15226): at WebRtc.ViEAndroidJavaAPI..ctor (Android.Content.Context) [0x00033] in XXX\WebRtc.Mono.Droid\ViEAndroidJavaAPI.cs:30 12-21 19:29:04.298 I/MonoDroid(15226): at WebRtc.Mono.Droid.WebRTCDemo.startMain () [0x0004b] in XXX\WebRtc.Mono.Droid\WebRTCDemo.cs:533 12-21 19:29:04.298 I/MonoDroid(15226): at WebRtc.Mono.Droid.WebRTCDemo.OnCreate (Android.OS.Bundle) [0x0028e] in XXX\WebRtc.Mono.Droid\WebRTCDemo.cs:313 12-21 19:29:04.298 I/MonoDroid(15226): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/d23a19bf/source/monodroid/src/Mono.Android/platforms/android-17/src/generated/Android.App.Activity.cs:2119 12-21 19:29:04.298 I/MonoDroid(15226): at (wrapper dynamic-method) object .705dc6ba-9c58-4bcd-a8a2-f12584a9175f (intptr,intptr,intptr) |
Finally after digging I found this posting Native library integration which basically state
you cannot sanely use P/Invoke to invoke the native method. You must instead use JNI to invoke the Java-side native method.Basically because this is Java native C/C++ interface we are to invoke, you cannot do this like normal non JNI wrapped C/C++ methods.
This is pushing me in a direction that I initially hoped I could avoid (mainly due to my limited knowledge in the area), JNI.
Later: I did some (quite a bit) reading, namely I found these links useful:
Interop with Native Libraries
Java Integration Overview
Working With JNI
In the next posting in this series I manage to invoke the native methods.
No comments:
Post a Comment