使用Ninja构建CLD3 JVM封装库在Windows编译报错求助
解决Windows下CLD3封装库的编译类型转换错误
这个问题的核心是跨平台的整数与指针类型长度不匹配,咱们一步步拆解原因和解决方案:
为什么Windows报错,其他系统正常?
在64位系统中:
- Linux/macOS的
long类型是64位,和指针(void*)的长度一致,所以把指针转成long再转回来不会有截断,编译器也不会触发警告。 - Windows的64位架构(x86_64)中,
long仍然是32位,而指针是64位。当你把64位指针存到32位long里时会丢失高位,编译器通过-Werror把这个潜在危险的警告升级成了错误。
解决方案:使用跨平台安全的指针存储类型
1. 替换C++中的long为标准指针整数类型
C++标准库提供了intptr_t(定义在<cstdint>头文件中),这是一个专门用来存储指针的整数类型,长度和当前平台的指针一致,完美解决跨平台问题。
2. 直接用指针操作缓冲区,避免整数转指针的冗余转换
原来的代码把缓冲区地址转成long再一步步偏移,既不安全也容易出错,直接用char*来操作缓冲区会更直观。
修改后的C++代码如下:
#include <cstdint> // 引入intptr_t的定义 #include <cstring> void detect(intptr_t ptr, const char *text, char *into) { chrome_lang_id::NNetLanguageIdentifier *nptr = reinterpret_cast<chrome_lang_id::NNetLanguageIdentifier*>(ptr); chrome_lang_id::NNetLanguageIdentifier::Result res = nptr->FindLanguage(text); char* current = into; // 写入probability *reinterpret_cast<float*>(current) = res.probability; current += sizeof(float); // 写入proportion *reinterpret_cast<float*>(current) = res.proportion; current += sizeof(float); // 写入is_reliable *reinterpret_cast<short*>(current) = res.is_reliable; current += sizeof(short); // 写入语言字符串长度 const int lang_size = static_cast<int>(res.language.size()); *reinterpret_cast<int*>(current) = lang_size; current += sizeof(int); // 写入语言字符串(包括末尾的'\0') std::memcpy(current, res.language.c_str(), lang_size + 1); }
3. JVM端代码无需修改
Kotlin中的Long是64位类型,和intptr_t在64位平台上的长度匹配,所以原来的Kotlin代码可以直接使用,不需要调整。
额外注意点
- 确保编译时包含
<cstdint>头文件,否则intptr_t会未定义。 - 把
memccpy换成memcpy更稳妥,memccpy的行为是遇到指定字符就停止复制,这里我们需要完整复制字符串(包括终止符),memcpy更符合需求。 - 如果你的项目还支持32位Windows,
intptr_t会自动变成32位,依然能和JVM的Long兼容(JVM的Long在32位系统上也是64位,但存储指针时会自动截断到32位,不影响正确性)。
这样修改后,Windows、Linux和macOS平台都能正常编译,而且代码的跨平台安全性也提升了。
内容的提问来源于stack exchange,提问作者Naor Tedgi
相关产品推荐
相关产品推荐

