iTXTech / mirai-native

强大的 mirai 原生插件加载器
GNU Affero General Public License v3.0
370 stars 141 forks source link

将字符串编码转换移动到JVM #32

Closed mrhso closed 3 years ago

mrhso commented 4 years ago

GB 18030 转换部分依赖 Windows 的原生 API,然而 Wine 下并没有 CP 54936。 也许可以引入 libiconv。当然,现在的 libiconv 并不遵循 GB 18030-2000,所以可以使用我修改过的 libiconv。 考虑到 libiconv 是 LGPL,我把 Patch 也附上了。 libiconv 1.16 GB 18030-2000.7z

PeratX commented 4 years ago

GB 18030 转换部分依赖 Windows 的原生 API,然而 Wine 下并没有 CP 54936。 也许可以引入 libiconv。当然,现在的 libiconv 并不遵循 GB 18030-2000,所以可以使用我修改过的 libiconv。 考虑到 libiconv 是 LGPL,我把 Patch 也附上了。 libiconv 1.16 GB 18030-2000.7z

本来考虑的解决方案是可配置的codepage

PeratX commented 4 years ago

看了一下,wine应该有936的,那就可以配置成936

PeratX commented 4 years ago

可配置的codepage已更新

mrhso commented 4 years ago

不过设成 CP 936 的话倒是有个问题,GB 18030 是 UTF,但 GBK 不是。

PeratX commented 4 years ago

不过设成 CP 936 的话倒是有个问题,GB 18030 是 UTF,但 GBK 不是。

能兼容中文字符集的插件就行了,当然需要考虑一些特殊转义,比如CQ中的emoji在GBK中可能就不存在了(是不是这样?

mrhso commented 4 years ago

能兼容中文字符集的插件就行了

(总感觉……)

当然需要考虑一些特殊转义,比如CQ中的emoji在GBK中可能就不存在了(是不是这样?

然而就算用了 CQ:emoji,用原生绘文字字符发送的插件同样完蛋……(毕竟非易语言插件也不少)

PeratX commented 4 years ago

能兼容中文字符集的插件就行了

(总感觉……)

当然需要考虑一些特殊转义,比如CQ中的emoji在GBK中可能就不存在了(是不是这样?

然而就算用了 CQ:emoji,用原生绘文字字符发送的插件同样完蛋……(毕竟非易语言插件也不少)

那可以直接配置成UTF的codepage呀

mrhso commented 4 years ago

其实我倒是很好奇,这各种 length * 2 + 1 到底怎么来的……

PeratX commented 4 years ago

可能是单字节编码转换到双字节编码需要两倍的空间,结尾还要多加个\0,所以+1 而且试过不+1会溢出错误。。。

mrhso commented 4 years ago

可能是单字节编码转换到双字节编码需要两倍的空间,结尾还要多加个\0,所以+1 而且试过不+1会溢出错误。。。

那为甚么不是 +2? (0x00 0x00)

PeratX commented 4 years ago

可能是单字节编码转换到双字节编码需要两倍的空间,结尾还要多加个\0,所以+1 而且试过不+1会溢出错误。。。

那为甚么不是 +2? (0x00 0x00)

其实是看csdn+StackOverflow写的这块

Prcuvu commented 4 years ago

https://github.com/iTXTech/mirai-native/blob/master/native/native.cpp#L63-L71

GbToJstring 函数中,strlen 函数得到的是字节数吗?如果是完整字符的个数,是不行的。

参见:MultiByteToWideChar function (stringapiset.h) - Win32 apps | Microsoft Docs

-param cbMultiByte [in]

Size, in bytes, of the string indicated by the lpMultiByteStr parameter. Alternatively, this parameter can be set to -1 if the string is null-terminated. Note that, if cbMultiByte is 0, the function fails. If this parameter is -1, the function processes the entire input string, including the terminating null character. Therefore, the resulting Unicode string has a terminating null character, and the length returned by the function includes this character. If this parameter is set to a positive integer, the function processes exactly the specified number of bytes. If the provided size does not include a terminating null character, the resulting Unicode string is not null-terminated, and the returned length does not include this character.

-param cchWideChar [in]

Size, in characters, of the buffer indicated by lpWideCharStr. If this value is 0, the function returns the required buffer size, in characters, including any terminating null character, and makes no use of the lpWideCharStr buffer.

PeratX commented 4 years ago

如果觉得有问题可以直接pr,这个我不懂。

PeratX commented 3 years ago

我想了一下,可以将编码转换放到jvm来做,native只做桥的功能

PeratX commented 3 years ago

jvm和native传递字符串直接采用字节数组,native得到字节数组直接转换成const char*再传递给插件即可

mrhso commented 3 years ago

我觉得没甚么问题,Java 里面 GB 18030 的确是 GB 18030-2000。

PeratX commented 3 years ago

目前已经大部分实现

mrhso commented 3 years ago

那么「小部分」是指?

PeratX commented 3 years ago

小部分指的是,這些API沒有經過全面測試。