0

我有一个具有以下签名的 C++ 方法:

int cppGetData(string& data);

它应该从 Java 方法中调用。

第一版

byte[] javaGetData();

null如果cppGetData返回非零返回码,则应该返回。

我知道我必须写这样的东西:

JNIEXPORT jbyteArray JNICALL jniGetData(JNIEnv * env, jobject thisObj) 
(
  string data;
  if (cppGetData(data))
  {
    return NULL;
  }

  jbyteArray jData = env->NewByteArray(data.size());
  env->SetByteArrayRegion(jData, 0, data.size(), (jbyte *)data.c_str());

  return jData;
}

我的问题是我失去了cppGetData. 另一方面,Java没有引用返回,所以我很困惑。如何返回byte[]整数状态?

当然,我可以有一个包装器,像这样:

public class ByteArrayWrapper{
  public byte[] bytes;
}

然后 javaGetData 变成:

int javaGetData(ByteArrayWrapper wrapper);

这太可怕了。就 API 签名和jniGetData方法复杂性而言。

有没有更好的办法?

4

2 回答 2

2

最接近你所拥有的东西是

native static int cppGetData(ByteBuffer bb);

这并不比你在 ByteBuffer 中所拥有的更好,它是一个 byte[] 的包装器,但它使用内置类来做到这一点。一个限制是底层 byte[] 不可调整大小,但您可以通过设置limit.

另一种选择是使用

native static int cppGetData(byte[][] bytes)

这允许您返回不同的字节[]。

或者你可以

int[] num = { 0 };

native static byte[] cppGetData(int[] num)

或更新对象的字段,例如

class CallsCppGetData {
    int num;
    byte[] bytes;

    native void cppGetData(); // sets this.num and this.bytes.
}

返回多个值的解决方案是使用一个对象。

无论是你

  • 更新您正在调用该方法的对象的多个字段。
  • 包装多个字段时返回一个对象。
  • 传递要设置的可变对象。例如,您可以传递一个int[]包含一个元素的元素。

虽然创建新类很糟糕,但拥有一个没有一个结果的方法也是如此。;)

于 2012-11-21T18:23:29.567 回答
0

如果传递一个对象是个问题,我只看到另一个解决方案:有两个单独的方法

jint prepareData();
jbyteArray getData();

仅当第一个返回零时才调用第二个,如您指定的那样。当然,这个解决方案不是特别原子,也不是 thredsafe,因为它需要在 C 端的调用之间存储持久数据。除非您将两个本机调用包装在 Java 端的同步块中。但是许多无处不在的框架无所畏惧地使用这种技术在其他函数调用之后报告一些常见的内部状态。GetLastError想到了Win32 API ,虽然那个是线程安全的。

于 2012-11-21T22:10:22.033 回答