Given this method in a c++
library (Gifflen, animated gif maker):
JNIEXPORT jint JNICALL Java_org_jiggawatt_giffle_Giffle_Init(JNIEnv *ioEnv, jobject ioThis,
jstring gifName, jint w, jint h, jint numColors, jint quality, jint frameDelay) { ... }
And this signature to access it:
extern "C"
{
JNIEXPORT jint JNICALL Java_org_jiggawatt_giffle_Giffle_Init(JNIEnv *ioEnv,
jobject ioThis, jstring gifName, jint w, jint h, jint numColors, jint quality,
jint frameDelay);
}
Shouldn't the p/invoke be similar to that?
[DllImport("libgifflen.so", CharSet = CharSet.Ansi)]
public static extern int Java_org_jiggawatt_giffle_Giffle_Init(string gifName, int w,
int h, int numColors, int quality, int frameDelay);
I have a program that basically just tries to access that Init methods.
I'm loading the library successfully: Java.Lang.JavaSystem.LoadLibrary("gifflen");
Then it seems I'm pointing to the correct method, but it crashes as soon as it enters in the method.
I'm calling Init with same values as in the java demo application (and with basically the same values as in all my other implementations of this gif encoder since this is the same code-base for all libraries):
var pathForResult = "/storage/sdcard0/giftest/giffleResult.gif";
int optCol = 256, optQuality = 100, optDelay = 4;
Giffle.Init (pathForResult , 256, 256, optCol, optQuality, optDelay);
Then I'm getting this crash:
[mono-rt] at <unknown> <0xffffffff>
[mono-rt] at (wrapper managed-to-native) org.jiggawatt.giffle.Giffle.Java_org_jiggawatt_giffle_Giffle_Init (string,int,int,int,int,int) <IL 0x00046, 0xffffffff>
[mono-rt] at org.jiggawatt.giffle.Giffle.Init (string,int,int,int,int,int) [0x00001] in c:\Users\user.name\Projects\Giffle\Giffle\Giffle.cs:20
[mono-rt]
[mono-rt] Attempting native Android stacktrace:
[mono-rt]
[mono-rt] at Java_org_jiggawatt_giffle_Giffle_Init+19 [0x6433c83c]
[mono-rt] at ???+12272 [0x6467fff0]
[libc] Fatal signal 11 (SIGSEGV) at 0x6f7475d3 (code=1), thread 29670 (myapp.someapp)
I'm I using native libraries incorrectly in my Xamarin application?
Code for bindings
using System;
using System.Runtime.InteropServices;
namespace org.jiggawatt.giffle
{
public class Giffle {
public const string GIFFLE_DLL_NAME = "libgifflen.so";
[DllImport(GIFFLE_DLL_NAME, CharSet = CharSet.Ansi)]
public static extern int Java_org_jiggawatt_giffle_Giffle_Init(string gifName, int w, int h, int numColors, int quality, int frameDelay);
[DllImport(GIFFLE_DLL_NAME, CharSet = CharSet.Ansi)]
public static extern void Java_org_jiggawatt_giffle_Giffle_Close();
[DllImport(GIFFLE_DLL_NAME, CharSet = CharSet.Ansi)]
public static extern int Java_org_jiggawatt_giffle_Giffle_AddFrame(int[] inArray);
}
}
Code for test
var external = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var appPath = System.IO.Path.Combine (external, "giftest");
if (!Directory.Exists (appPath)) {
Directory.CreateDirectory (appPath);
}
var t = "/storage/sdcard0/giftest/result3.gif";
File.Delete (t);
int optCol = 256, optQuality = 100, optDelay = 4;
Giffle.Init (t, 256, 256, optCol, optQuality, optDelay);
var image = Bitmap.CreateBitmap (256, 256, Bitmap.Config.Argb8888);
for (int i = 0; i < 50; i++) {
image = Bitmap.CreateBitmap (256, 256, Bitmap.Config.Argb8888);
image.EraseColor (Color.Argb (255, 255 - i * 4, i * 4, i * 4));
int[] pixelsCopy = new int[image.Width * image.Height];
image.LockPixels ();
image.GetPixels(pixelsCopy, 0, image.Width, 0, 0, image.Width, image.Height);
image.UnlockPixels ();
image.Recycle ();
Giffle.Java_org_jiggawatt_giffle_Giffle_AddFrame (pixelsCopy);
}
Giffle.Java_org_jiggawatt_giffle_Giffle_Close ();
You can only skip this arguments "JNIEnv *ioEnv, jobject ioThis" like you do in java if your c++ code does nothing with this arguments, otherwise you should also include this arguments in your function definition. And you should not use C# types, use java types instead.
[DllImport("libgifflen.so", EntryPoint = "Java_org_jiggawatt_giffle_Giffle_Init", CharSet = CharSet.Ansi)]
public static extern int Init(IntPtr env, IntPtr thiz, IntPtr gifName, IntPtr w,
IntPtr h, IntPtr numColors, IntPtr quality, IntPtr frameDelay);
Call your function like this:
Init(JNIEnv.Handle, System.IntPtr.Zero, (new Java.Lang.String("Your gif name")).Handle, (new Java.Lang.Integer(w)).Handle,
(new Java.Lang.Integer(h)).Handle, (new Java.Lang.Integer(numColors)).Handle, (new Java.Lang.Integer(quality)).Handle, (new Java.Lang.Integer(frameDelay)).Handle);
Check also this answer:
Load .so file in Xamarin.Android
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With