Reputation: 8064
I have a JNA Java interface for a C function mpv_set_option_string
defined as:
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);
}
When I call this like this:
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");
I get an error back (-5
) from the last call, indicating the option (keep-open
) is not found.
However, if I change the JNA function signature to:
int mpv_set_option_string(long handle, byte[] name, byte[] data);
...and then call it like this:
error = MPV.INSTANCE.mpv_set_option_string(
handle,
"keep-open\0".getBytes(StandardCharsets.UTF_8),
"always\0".getBytes(StandardCharsets.UTF_8)
);
...it returns no error (0
) and works correctly (or so it seems).
What I don't get is, JNA is supposed to encode String
by default as char *
with UTF-8 encoding and NUL
terminated (exactly what I do manually), yet I get different results.
Anyone able to shed some light on this?
Upvotes: 1
Views: 1202
Reputation: 10069
You shouldn't be passing W32OPTIONS to a library that isn't a WIN32 API.
By default, JNA maps String
to char*
, so removing the options should fix the issue for you.
You should also be using an explicit native type for your handle instead of Java long
. Pointer
is probably correct in this case.
Upvotes: 1
Reputation: 8064
Looks like I found the issue, although I'm not 100% sure what is happening.
It seems that using W32APIOptions.DEFAULT_OPTIONS
means it will use the UNICODE settings (because w32.ascii
property is false
). This looked okay to me, as mpv-1.dll
works with UTF-8 strings only, which is Unicode.
However, now I'm guessing that in this case it means it will call a wide-char version of the library function (and if that doesn't exist, still call the original function), and probably means it encodes Strings with two bytes per character. This is because most Win32 libraries have an ASCII and WIDE version of methods accepting strings, but nothing for UTF-8.
Since mpv-1.dll
only accepts UTF-8 (and isn't really Win32), strings should be just encoded as bytes in UTF-8 format (basically, just leave them alone). To let JNA know this, either donot pass a W32APIOptions
map at all, or select the ASCII_OPTIONS
manually.
Upvotes: 1