1

我正在编写一个执行安全模块(例如加密、签名等)的程序...我用 C 语言编写了具有上述功能的库。现在我使用 jni 从 java 调用这个 C 本机函数。

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

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

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

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

4

2 回答 2

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

这应该足以传达这个想法。它是从工作代码中转述出来的,但未经当前形式的测试。

于 2012-07-14T22:17:31.113 回答
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);
}

根据您的性能考虑(即,如果您想确保避免复制数组数据,或避免并发访问字节数组),这里有一个使用GetPrimitiveArrayCritical.

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

于 2012-07-15T13:09:28.320 回答