如何将值存储在传递给JNI本机C调用的Java参数中

时间:2012-07-14 09:39:36

标签: java java-native-interface

我正在编写一个执行加密,签名等安全模块的程序......我在C中编写了库,它完成了上述功能。现在我使用jni从java调用这个C本机函数。

我遇到的问题是我无法将结果(签名数据或加密数据)存储到java传递的参数中。我想将结果存储在我收到的参数中。请帮我。非常感谢。

以下是我在java中用来调用本机函数的API

sign("sign",byte[] file,int filelen,byte[] output,int outputlen)

在本机C调用中,我将在“文件”上执行登录,该文件是由输入文件内容组成的缓冲区,我想将其存储到输出中。我怎么能这样做,任何人都可以帮助我,我没有找到任何相关信息。

2 个答案:

答案 0 :(得分:1)

通常,使用直接ByteBuffer调用本机库。

界面为MyClass.submit(ByteBuffer source, ByteBuffer dest)

static jmethodID ByteBuffer_position;
static jmethodID ByteBuffer_limit;

// Find method id's for ByteBuffer methods.
JNIEXPORT jint JNICALL Java_MyClass_initAPI
    (JNIEnv *env, jclass thisj) {
  jint error = 0;

  ByteBuffer_position = (*env)->GetMethodID(env, byteBufferClass, "position", "()I");
  if (ByteBuffer_position == NULL) error = -1;
  ByteBuffer_limit = (*env)->GetMethodID(env, byteBufferClass, "limit", "()I");
  if (ByteBuffer_limit == NULL) error = -1;

  return error;
}

// Get ByteBuffer pointers and sizes and encrypt
// Expects source buffer's position to indicate end of source
// Expects dest buffer's limit to indicate max output length
JNIEXPORT jint JNICALL Java_MyClass_submit (JNIEnv *env, jobject thisj,
    jobject sourceBuffer, jobject destBuffer ) {
    jint error = 0;

    unsigned char* sourcePtr = (*env)->GetDirectBufferAddress(env, source);
    unsigned char* destPtr = (*env)->GetDirectBufferAddress(env, dest);
    jlong sourceLen = (*env)->CallIntMethod(env, source, ByteBuffer_position);
    jlong destLen = (*env)->CallIntMethod(env, dest, ByteBuffer_limit);

    // Encrypt sourcePtr --> destPtr

    return error;
}

这应该足以让我们了解这个想法。它是从工作代码中解释的,但在当前形式中未经测试。

答案 1 :(得分:0)

以下代码允许您的本机代码直接访问两个原始字节数组输入的内容。

JNIEXPORT void JNICALL Java_*mypackage*_sign(JNIEnv* env, jbytearray input, jint ilen, jbytearray output, jint olen) {
  char* pinput = (*env)->GetByteArrayElements(env, input, NULL);
  char* poutput = (*env)->GetByteArrayElements(env, output, NULL);

  sign(pinput, ilen, poutput, olen);

  (*env)->ReleaseByteArrayElements(env, input, pinput, 0);
  (*env)->ReleaseByteArrayElements(env, output, poutput, 0);
}

取决于您的性能注意事项(即,如果您希望确保避免复制数组数据,或避免对字节数组进行并发访问),here is an example使用GetPrimitiveArrayCritical

仅当您需要在本机代码和Java代码之间共享缓冲区的时间超过单个函数调用的持续时间时,才建议使用NIO /直接缓冲区。