Unicode const char*使用JNI和C ++

 2023-01-20    294  

问题描述

简单的问题.如何使用JNI和C ++?

这是我的问题,也是我已经尝试的内容:

Unicode const char*使用JNI和C ++

const char* value = (some value from server);
(*env)->NewStringUTF(value);

这里的问题是NewsTringUtf返回UTF字符串,它不喜欢某些非UTF8字符(有点明显,但值得一试).

尝试2,使用新闻流:

const char* value = (some value from server);
(*env)->NewString(value, strlen(value));

当新闻弦接受并返回Unicode字符串时,strlen(value)方法不起作用,因为它需要一个jsize param,而不仅仅是一个良好的ol’size_t或长度.

我们如何获得JSize?根据(非常少量的)文档和在线示例,您可以从Jintarray中获得JSize.
我找不到有关如何将const char*转换为某种jarray的信息,无论如何这可能是一个坏主意.

另一个选项是将jsize从size_t中的int中取出,我也没有成功.

有人遇到这个问题,还是对如何解决问题有建议?
似乎JSize是我缺少Unicode转换的关键.
另外,我正在使用JNI和Android NDK,以防万一它可以帮助任何人.

谢谢.

编辑
我刚刚意识到新闻结构也期待着JCHAR*,因此其签名为(JCHAR*,JSize).这意味着即使使用jsize const char*也不会编译.

编辑2
使用NewsTringUtf方法时,这是在运行时抛出的例外.这与@Fadden在谈论的内容有关:

JNI WARNING: NewStringUTF input is not valid Modified UTF-8: illegal start byte 0xb7 03string: ' : Method(d6, us-dev1-api, 0), , 訩�x�m�P)

推荐答案

正如错误消息显示的那样,您的字符*不是有效的修改-UTF8,因此JVM中止了.

您有两种避免它们的方法.

  1. 检查char*内容以避免崩溃.

Android Art Check_jni.cc中的检查逻辑如下
art/+/35e827a/runtime/check_jni.cc#1273

jstring toJString(JNIEnv* env, const char* bytes) {
    const char* error = nullptr;
    auto utf8 = CheckUtfBytes(bytes, &error);
    if (error) {
        std::ostringstream msg;
        msg << error << " 0x" << std::hex << static_cast<int>(utf8);
        throw std::system_error(-1, std::generic_category(), msg.str());
    } else {
        return env->NewStringUTF(bytes);
    }

这样,您始终得到有效的jstring.

  1. 使用字符串构造函数从jbyteArray构建.
jstring toJString(JNIEnv *env, const char *pat) {
    int len = strlen(pat);
    jbyteArray bytes = env->NewByteArray(len);
    env->SetByteArrayRegion(bytes, 0, len, (jbyte *) pat);
    jstring encoding = env->NewStringUTF("utf-8");
    jstring jstr = (jstring) env->NewObject(java_lang_String_class,
            java_lang_String_init, bytes, encoding);
    env->DeleteLocalRef(encoding);
    env->DeleteLocalRef(bytes);
    return jstr;
}

以这种方式,您只避免崩溃,但是字符串可能仍然没有有效,并且您将记忆复制两次,表现不佳.

加上代码:

inline bool checkUtfBytes(const char* bytes) {
  while (*bytes != '\0') {
    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
    // Switch on the high four bits.
    switch (*utf8 >> 4) {
      case 0x00:
      case 0x01:
      case 0x02:
      case 0x03:
      case 0x04:
      case 0x05:
      case 0x06:
      case 0x07:
        // Bit pattern 0xxx. No need for any extra bytes.
        break;
      case 0x08:
      case 0x09:
      case 0x0a:
      case 0x0b:
        // Bit patterns 10xx, which are illegal start bytes.
        return false;
      case 0x0f:
        // Bit pattern 1111, which might be the start of a 4 byte sequence.
        if ((*utf8 & 0x08) == 0) {
          // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
          // We consume one continuation byte here, and fall through to consume two more.
          utf8 = reinterpret_cast<const uint8_t*>(bytes++);
          if ((*utf8 & 0xc0) != 0x80) {
            return false;
          }
        } else {
          return false;
        }
        // Fall through to the cases below to consume two more continuation bytes.
      case 0x0e:
        // Bit pattern 1110, so there are two additional bytes.
        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
        if ((*utf8 & 0xc0) != 0x80) {
          return false;
        }
        // Fall through to consume one more continuation byte.
      case 0x0c:
      case 0x0d:
        // Bit pattern 110x, so there is one additional byte.
        utf8 = reinterpret_cast<const uint8_t*>(bytes++);
        if ((*utf8 & 0xc0) != 0x80) {
          return false;
        }
        break;
    }
  }
  return true;
}

以上所述是小编给大家介绍的Unicode const char*使用JNI和C ++,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/26044.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。