JNI将接口作为函数传递给CPP代码

huangapple go评论63阅读模式
英文:

JNI pass interface as function to CPP code

问题

我有一个在CPP代码中定义的函数,如下:

using Data = std::vector<byte>;


void sign(const std::function<Data(Data)> externalSigner) {
   ...
}

我需要将Java接口作为参数传递给这个函数。

public interface ByteArrayProvider {
    byte[] provide(byte[] data);
}

我能够找到我的接口,调用它并获取结果。但我不知道如何将它传递给C++函数。

英文:

I have a function in CPP code which is defined as

using Data = std::vector<byte>;


void sign(const std::function<Data(Data)> externalSigner) {
   ...
}

And I need to pass java interface as a parameter to this function.

public interface ByteArrayProvider {
    byte[] provide(byte[] data);
}

I'm able to find my interface, call and get result. But I can't figure out how to pass it to C++ function.

答案1

得分: 2

NativeLib.java:

package com.example.nativelib;

public class NativeLib {
  static { System.loadLibrary("nativelib"); }
  public static native void sign(ByteArrayProvider bap);
}

nativelib.cpp:

#include <jni.h>
#include <vector>

Data myFunc(JNIEnv* env, jobject bap, Data data) {
  jbyteArray a = env->NewByteArray(data.size());
  env->SetByteArrayRegion(a, 0, data.size(), (const jbyte*)data.data());

  jclass cls = env->GetObjectClass(bap);
  jmethodID provide = env->GetMethodID(cls, "provide", "([B)[B");
  jbyteArray aret = (jbyteArray)env->CallObjectMethod(bap, provide, a);

  jbyte* bytes = env->GetByteArrayElements(aret , 0);
  std::vector<char> ret(bytes, bytes + env->GetArrayLength(aret));
  env->ReleaseByteArrayElements(aret, bytes, JNI_ABORT);
  return ret;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_nativelib_NativeLib_sign(JNIEnv* env, jclass clazz, jobject data) {
    sign(std::bind(myFunc, env, data, std::placeholders::_1));
}

Then you can simply call (bap is your ByteArrayProvider):

NativeLib.sign(bap);
英文:

First you have to create a new native library inside your project under File &gt; New &gt; New Module... &gt; Android Native Library. I selected Java as language.

NativeLib.java:

package com.example.nativelib;

public class NativeLib {
  static { System.loadLibrary(&quot;nativelib&quot;); }
  public static native void sign(ByteArrayProvider bap);
}

nativelib.cpp:

#include &lt;jni.h&gt;
#include &lt;vector&gt;

Data myFunc(JNIEnv* env, jobject bap, Data data) {
  jbyteArray a = env-&gt;NewByteArray(data.size());
  env-&gt;SetByteArrayRegion(a, 0, data.size(), (const jbyte*)data.data());

  jclass cls = env-&gt;GetObjectClass(bap);
  jmethodID provide = env-&gt;GetMethodID(cls, &quot;provide&quot;, &quot;([B)[B&quot;);
  jbyteArray aret = (jbyteArray)env-&gt;CallObjectMethod(bap, provide, a);

  jbyte* bytes = env-&gt;GetByteArrayElements(aret , 0);
  std::vector&lt;char&gt; ret(bytes, bytes + env-&gt;GetArrayLength(aret));
  env-&gt;ReleaseByteArrayElements(aret, bytes, JNI_ABORT);
  return ret;
}

extern &quot;C&quot;
JNIEXPORT void JNICALL
Java_com_example_nativelib_NativeLib_sign(JNIEnv* env, jclass clazz, jobject data) {
    sign(std::bind(myFunc, env, data, std::placeholders::_1));
}

Then you can simply call (bap is your ByteArrayProvider):

NativeLib.sign(bap);

huangapple
  • 本文由 发表于 2023年3月7日 16:17:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659459.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定