Xamarin.android Xamarin与jni集成的正确方法

Xamarin.android Xamarin与jni集成的正确方法,xamarin.android,Xamarin.android,我正在将我的Android项目转移到Xamarin。Android项目引用了一个外部库libmyencoder.so.下面是它公开的一个函数的签名: JNIEXPORT jint JNICALL encodeData (JNIEnv *, jclass, jlong, jobject, jint, jobject, jint); 在Java方面,本机方法声明如下: static native int encodeData(long handle, ByteBuffer inpu

我正在将我的Android项目转移到Xamarin。Android项目引用了一个外部库
libmyencoder.so.
下面是它公开的一个函数的签名:

JNIEXPORT jint JNICALL encodeData (JNIEnv *, jclass, jlong,
    jobject, jint, jobject, jint);
在Java方面,本机方法声明如下:

static native int encodeData(long handle,
    ByteBuffer input, int inputLen, ByteBuffer output, int maxOutputLen);
[DllImport ("myencoder",EntryPoint="encodeData")]
public extern static void encodeData(long handle, ByteBuffer input,
   int inputLen, ByteBuffer output, int maxOutputLen);
在Xamarin文档中,我看到了几个使用dllimport的示例。基于此,我想我可以声明我的C#方法如下:

static native int encodeData(long handle,
    ByteBuffer input, int inputLen, ByteBuffer output, int maxOutputLen);
[DllImport ("myencoder",EntryPoint="encodeData")]
public extern static void encodeData(long handle, ByteBuffer input,
   int inputLen, ByteBuffer output, int maxOutputLen);
这个C#定义正确吗

令人困惑的是,尽管我已经定义了入口点,但我没有在任何地方特别提到本机方法的签名。这将是:

(JLjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I
Xamarin引擎是否足够聪明,能够根据方法声明推断出正确的签名


另外,我应该将
libmyencoder.so
复制到Xamarin项目目录中的哪个位置?问候。

不幸的是,来自Xamarin的本地呼叫没有很好的记录。在github上浏览了一些源代码并进行了一些实验之后,我发现
Xamarin不依赖Jni。你不必担心坚持Jni的做事方式。例如,第一个参数不必是
JNIEnv*
类型。此外,您可以简单地将指针而不是作业对象作为函数参数传递。

不幸的是,来自Xamarin的本机调用没有很好的文档记录。在github上浏览了一些源代码并进行了一些实验之后,我发现 Xamarin不依赖Jni。你不必担心坚持Jni的做事方式。例如,第一个参数不必是
JNIEnv*
类型。此外,您可以简单地将指针而不是作业对象作为函数参数传递。

将“jniLibs”Java Android Content文件夹(包括.so文件)复制到Xamarin.Android项目下的“lib”文件夹中,例如:

将.so文件的“构建操作”设置为“AndroidNativeLibrary”。

方法的签名应如下所示:

[DllImport ("myencoder",EntryPoint="encodeData")]
public extern static void encodeData(IntPtr env, IntPtr class, IntPtr handle, IntPtr input, IntPtr inputLen, IntPtr output, IntPtr maxOutputLen);
您使用的是jint、jlong、jobject,因此不能直接使用C#type,您必须使用java类型,例如在jint参数使用中,并且不能跳过JNIEnv*、jclass:

您必须使用java参数调用函数,例如:

Java.Nio.ByteBuffer inputSample = Java.Nio.ByteBuffer.Allocate(10);
Java.Nio.ByteBuffer outputSample = Java.Nio.ByteBuffer.Allocate(10);
System.IntPtr jClassSample = JNIEnv.FindClass(typeof(SomeClass));
Java.Lang.Long handleVal = new Java.Lang.Long(4);
Java.Lang.Integer inputLenVal = new Java.Lang.Integer(4);
Java.Lang.Integer maxOutputLenVal = new Java.Lang.Integer(4);

encodeData(JNIEnv.Handle, jClassSample, handleVal.Handle, inputSample.Handle, inputLenVal.Handle, outputSample.Handle, maxOutputLenVal.Handle);
有关更多详细信息,请查看我的回答:

将“jniLibs”Java Android内容文件夹(包括.so文件)复制到Xamarin.Android项目下的“lib”文件夹中,例如:

将.so文件的“构建操作”设置为“AndroidNativeLibrary”。

方法的签名应如下所示:

[DllImport ("myencoder",EntryPoint="encodeData")]
public extern static void encodeData(IntPtr env, IntPtr class, IntPtr handle, IntPtr input, IntPtr inputLen, IntPtr output, IntPtr maxOutputLen);
您使用的是jint、jlong、jobject,因此不能直接使用C#type,您必须使用java类型,例如在jint参数使用中,并且不能跳过JNIEnv*、jclass:

您必须使用java参数调用函数,例如:

Java.Nio.ByteBuffer inputSample = Java.Nio.ByteBuffer.Allocate(10);
Java.Nio.ByteBuffer outputSample = Java.Nio.ByteBuffer.Allocate(10);
System.IntPtr jClassSample = JNIEnv.FindClass(typeof(SomeClass));
Java.Lang.Long handleVal = new Java.Lang.Long(4);
Java.Lang.Integer inputLenVal = new Java.Lang.Integer(4);
Java.Lang.Integer maxOutputLenVal = new Java.Lang.Integer(4);

encodeData(JNIEnv.Handle, jClassSample, handleVal.Handle, inputSample.Handle, inputLenVal.Handle, outputSample.Handle, maxOutputLenVal.Handle);
有关更多详细信息,请查看我的回答: