将Boost :: uint64转换为Java的最有效方法

时间:2013-11-26 17:20:42

标签: java c++ boost java-native-interface

作为一个简短的例子,我有C ++ JNI代码,它将获取某些文件的文件大小,我想将其传递回Java。

A)这是一种理智的方法吗?

B)有没有更好的方法来执行此操作而不是将数据转储到String?

C ++代码段:

JNIEXPORT jstring JNICALL Java_test_TestClass_getNumBytes(...) {
  boost::uintmax_t numBytes = 0;
  try {
    numBytes = boost::filesystem::file_size(MY_GLOBAL_FILE_NAME);
  } catch(const boost::filesystem::filesystem_error& e) {
    return env->NewStringUTF("0");
  }

  return env->NewStringUTF(boost::lexical_cast<std::string>(numBytes));
}

Java代码段:

private native String getNumBytes();

public void doStuff() {
  final String s = getNumBytes();
  final BigInteger bi = new BigInteger(s);

  final StringBuilder sb = new StringBuilder("Comparing: ");
  sb.append(s).append(" to ").append(bi);

  System.out.println("Values should look the same: " + sb.toString());
}

假设Java无法访问MY_GLOBAL_FILE_NAME。

1 个答案:

答案 0 :(得分:0)

只需将boost::uintmax_t投射到jlong即可。可能的精度损失很可能仍然是一个理论问题。 Java中的任何I / O API都使用签名的long

如果您想为符号成为问题的大小做好准备,您仍然可以将值jlong传递给Java代码并将其修复到Java端,因为溢出不会破坏信息和该标志为溢出提供了一个易于检查的指标。

代码可能如下所示:

// 2⁶⁴
private static BigInteger twoP64=BigInteger.ZERO.flipBit(64);

public static BigInteger getNumBytes()
{
  long longValue=getNumByteNative();
  BigInteger i=BigInteger.valueOf(longValue);
  if(longValue<0) i=i.add(twoP64);
  return i;
}

private native long getNumByteNative();

这比在原生方面构建BigInteger容易得多。并且它允许您在Java方面有条件地进行,只要它适合long并且仅在必要时使用BigInteger(我猜不会)。