java - 使用 String 的 JNA 调用与使用 byte[] 的行为不同
问题描述
我有一个 C 函数的 JNA Java 接口,mpv_set_option_string
定义为:
public interface MPV extends StdCallLibrary {
MPV INSTANCE = Native.loadLibrary("lib/mpv-1.dll", MPV.class, W32APIOptions.DEFAULT_OPTIONS);
long mpv_create();
int mpv_initialize(long handle);
int mpv_set_option_string(long handle, String name, String data);
}
当我这样称呼它时:
System.setProperty("jna.encoding", "UTF8");
long handle = MPV.INSTANCE.mpv_create();
int error = MPV.INSTANCE.mpv_initialize(handle);
error = MPV.INSTANCE.mpv_set_option_string(handle, "keep-open", "always");
-5
我从上次调用中返回错误 ( ),表示keep-open
未找到选项 ( )。
但是,如果我将 JNA 函数签名更改为:
int mpv_set_option_string(long handle, byte[] name, byte[] data);
...然后这样称呼它:
error = MPV.INSTANCE.mpv_set_option_string(
handle,
"keep-open\0".getBytes(StandardCharsets.UTF_8),
"always\0".getBytes(StandardCharsets.UTF_8)
);
...它不返回错误(0
)并且可以正常工作(或者看起来如此)。
我没有得到的是,JNA 应该String
默认编码为char *
UTF-8 编码并NUL
终止(正是我手动执行的操作),但我得到了不同的结果。
任何人都可以对此有所了解吗?
解决方案
看起来我发现了这个问题,虽然我不是 100% 确定发生了什么。
似乎 usingW32APIOptions.DEFAULT_OPTIONS
意味着它将使用 UNICODE 设置(因为w32.ascii
属性是false
)。这对我来说看起来不错,因为mpv-1.dll
仅适用于 UTF-8 字符串,即 Unicode。
但是,现在我猜测在这种情况下,这意味着它将调用库函数的宽字符版本(如果不存在,仍然调用原始函数),并且可能意味着它用两个字节编码字符串每个字符。这是因为大多数 Win32 库都有接受字符串的 ASCII 和 WIDE 版本的方法,但对于 UTF-8 则没有。
由于mpv-1.dll
只接受 UTF-8(并不是真正的 Win32),因此字符串应该只编码为 UTF-8 格式的字节(基本上,不要管它们)。要让 JNA 知道这一点,要么W32APIOptions
根本不传递地图,要么ASCII_OPTIONS
手动选择。
推荐阅读
- java - 使用单线程从 2 个编年史队列中读取
- python - 分页器未显示适当的结果
- python - 使用 beautifulsoup 从 span 标签中抓取数据
- django - 如何在 HTML 页面上预填充 Django 动态添加的表单集字段
- eclipse - 从 Git 导入的 Eclipse 动态 web 项目:无法解析导入 XXX
- ios - SwiftUI | 如何覆盖 viewWillAppear 等生命周期方法
- splunk - 是否可以制作动态 splunk 仪表板?
- ruby - 在 Ruby on Rails 中将多态关联与 STI 或 MTI 混合
- c++ - 动态改变数组的大小并读入值。(无载体)
- javascript - onclick 按钮仅显示一次 toastr 并将错误消息分组到 toastr