将 Xamarin 与 jni 集成的正确方法

Proper way to integrate Xamarin with jni

我正在将我的 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);

在 Xamarin 文档中,我看到了一些使用 dllimport 的示例。基于此,我想我可以如下声明我的 C# 方法:

[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* 类型。此外,您可以简单地传递指针而不是 jobjects 作为函数参数。

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

将 .so 文件的 "Build Action" 设置为 "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# 类型,你必须使用 java 类型,例如在 jint 参数使用中,你不能跳过参数,如:JNIEnv *, j类:

并且您必须使用 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);

有关更多详细信息,请在此处查看我的答案:

Load .so file in Xamarin.Android