在Xamarin中正确绑定本机库

时间:2015-10-09 03:59:25

标签: android xamarin nativelibrary

c++库(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) { ... }

这个签名可以访问它:

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);
}

p / invoke不应该与那个相似吗?

[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);

我有一个基本上只是尝试访问Init方法的程序。

我正在成功加载库:Java.Lang.JavaSystem.LoadLibrary("gifflen");

然后我似乎指向了正确的方法,但它一进入方法就会崩溃。

我使用与java演示应用程序中相同的值调用Init(并且与此gif编码器的所有其他实现中的值基本相同,因为这是所有库的相同代码库):

var pathForResult = "/storage/sdcard0/giftest/giffleResult.gif";
int optCol = 256, optQuality = 100, optDelay = 4;
Giffle.Init (pathForResult , 256, 256, optCol, optQuality, optDelay);

然后我就崩溃了:

[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)

我是否在Xamarin应用程序中错误地使用本机库?

  

绑定代码

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);
    }
}
  

测试代码

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 ();

1 个答案:

答案 0 :(得分:1)

如果你的c ++代码对这个参数没有任何作用,你只能跳过这个参数“JNIEnv * ioEnv,jobject ioThis”,就像你在java中一样,否则你也应该在函数定义中包含这些参数。而且你不应该使用C#类型,而是使用java类型。

[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);

按照以下方式调用您的函数:

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);

也请回答这个问题:

Load .so file in Xamarin.Android