Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native Win32 API doesn't work #497

Closed
thibautd opened this issue Sep 2, 2015 · 13 comments
Closed

Native Win32 API doesn't work #497

thibautd opened this issue Sep 2, 2015 · 13 comments

Comments

@thibautd
Copy link

thibautd commented Sep 2, 2015

Hello,

I'm trying to bind the CreateFile function from kernel32 use direct mapping.

static {
    HashMap options = new HashMap() {
        {
            put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
            putAll(W32APIOptions.UNICODE_OPTIONS);
        }
    };
    NativeLibrary library = NativeLibrary.getInstance("kernel32", options);
    Native.register(SerialPortWindows.class, library);
}

public static native Kernel32.HANDLE CreateFile(String lpFileName, int dwDesiredAccess, int dwShareMode,
                                         WinBase.SECURITY_ATTRIBUTES lpSecurityAttributes,
                                         int dwCreationDisposition, int dwFlagsAndAttributes,
                                         Kernel32.HANDLE hTemplateFile);

It correctly finds the function, but the call fails, telling that my file doesn't exist. Here is the call:

handle = CreateFile(portName, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
            0, null, Kernel32.OPEN_EXISTING, 0, null);

If I replace my call with with the method privded by JNA platform:

handle = Kernel32.INSTANCE.CreateFile(portName, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
            0, null, Kernel32.OPEN_EXISTING, 0, null);

It works correctly. It might be related to the type mapping (probably the string convertion), but I don't understand why because I used the same options. Maybe I missed something and it's not a real issue.

Thanks for your amazing work.

@twall
Copy link
Contributor

twall commented Sep 3, 2015

You could start by replacing all non-primitive types with primitive types, and replace String with WString, thus eliminating type mapping as a potential source of the problem. If that works, you can then re-introduce the derived types until you again encounter the error, which should isolate the problem.

On Sep 2, 2015, at 5:32 PM, Thibaut DIRLIK notifications@github.com wrote:

Hello,

I'm trying to bind the CreateFile function from kernel32 use direct mapping.

static {
HashMap options = new HashMap() {
{
put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
putAll(W32APIOptions.UNICODE_OPTIONS);
}
};
NativeLibrary library = NativeLibrary.getInstance("kernel32", options);
Native.register(SerialPortWindows.class, library);
}

public static native Kernel32.HANDLE CreateFile(String lpFileName, int dwDesiredAccess, int dwShareMode,
WinBase.SECURITY_ATTRIBUTES lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes,
Kernel32.HANDLE hTemplateFile);

It correctly finds the function, but the call fails, telling that my file doesn't exist. Here is the call:

handle = CreateFile(portName, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
0, null, Kernel32.OPEN_EXISTING, 0, null);

If I replace my call with with the method privded by JNA platform:

handle = Kernel32.INSTANCE.CreateFile(portName, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
0, null, Kernel32.OPEN_EXISTING, 0, null);

It works correctly. It might be related to the type mapping (probably the string convertion), but I don't understand why because I used the same options. Maybe I missed something and it's not a real issue.

Thanks for your amazing work.


Reply to this email directly or view it on GitHub.

@thibautd
Copy link
Author

thibautd commented Sep 3, 2015

If I use W32APIOptions.ASCII_OPTIONS instead of UNICODE_OPTIONS it works. Which makes me think that the issue is really the string mapping.

@twall
Copy link
Contributor

twall commented Sep 3, 2015

It’s quite possible there’s a bug in the direct mapping handling the String=>WString type converter.

Try using UNICODE_OPTIONS, but explicitly declare the function to use WString as the argument type.

On Sep 3, 2015, at 7:42 AM, Thibaut DIRLIK notifications@github.com wrote:

If I use W32APIOptions.ASCII_OPTIONS instead of UNICODE_OPTIONS it works. Which makes me think that the issue is really the string mapping.


Reply to this email directly or view it on GitHub.

@twall
Copy link
Contributor

twall commented Sep 3, 2015

I’ve verified there’s at least a bug in automatic conversion from String to WString via type mapper when using direct mapping (and likely a corresponding bug in converting any such return type).

On Sep 3, 2015, at 7:51 AM, Timothy Wall twall@users.sf.net wrote:

It’s quite possible there’s a bug in the direct mapping handling the String=>WString type converter.

Try using UNICODE_OPTIONS, but explicitly declare the function to use WString as the argument type.

On Sep 3, 2015, at 7:42 AM, Thibaut DIRLIK notifications@github.com wrote:

If I use W32APIOptions.ASCII_OPTIONS instead of UNICODE_OPTIONS it works. Which makes me think that the issue is really the string mapping.


Reply to this email directly or view it on GitHub.

@thibautd
Copy link
Author

thibautd commented Sep 3, 2015

I can't test right now, but I'll take a look tonight. Anyway, happy you found a bug. I took a look yesterday and didn't find anything by reading the code. Could you explain the problem ?

@twall
Copy link
Contributor

twall commented Sep 3, 2015

There is special handling when the call dispatch encounters a type mapper or a NativeMapped type. Unfortunately these code blocks don't account for when those things convert into a String or WString, which are arguably legitimate native types. The dispatcher is left holding a pointer to a Java object instead of a native string pointer. It's odd that your case didn't encounter an error before actually making the native call.

Sent from my iPhone

On Sep 3, 2015, at 10:26 AM, Thibaut DIRLIK notifications@github.com wrote:

I can't test right now, but I'll take a look tonight. Anyway, happy you found a bug. I took a look yesterday and didn't find anything by reading the code. Could you explain the problem ?


Reply to this email directly or view it on GitHub.

@thibautd
Copy link
Author

thibautd commented Sep 3, 2015

I just tested with WString instead of String in CreateFile's signature, doing a call like this:

CreateFile(new WString(portName), Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
        0, null, Kernel32.OPEN_EXISTING, 0, null);

And it works correctly with UNICODE_OPTIONS. So I think your guess about the issue is right. Is the fix complicated to do ?

@twall
Copy link
Contributor

twall commented Sep 4, 2015

It’s turning out to be a little more complicated than I expected, mainly in handling the general case of a type mapper or NativeMapped spitting out a String, WString, or NIO Buffer (which all claim to be supported in NativeMapped javadoc). Those types require temporary allocation of memory or other setup/teardown, and while the direct mapping code accounts for that in some cases, the type mapped/native mapped code runs through a different path making it difficult to re-use the existing setup/teardown methods.

Nonetheless I expect to get a fix in before the next release.

On Sep 3, 2015, at 3:58 PM, Thibaut DIRLIK notifications@github.com wrote:

I just tested with WString instead of String in CreateFile's signature, doing a call like this:

CreateFile(new WString(portName), Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
0, null, Kernel32.OPEN_EXISTING, 0, null);

And it works correctly with UNICODE_OPTIONS. Si I think your guess about the issue is right. Is the fix complicated to do ?


Reply to this email directly or view it on GitHub.

@thibautd
Copy link
Author

thibautd commented Sep 4, 2015

Ok. Thanks for your support @twall !

@twall
Copy link
Contributor

twall commented Sep 5, 2015

Fixed by #498

@twall twall closed this as completed Sep 5, 2015
@boscogh
Copy link

boscogh commented Jun 17, 2016

I tested performance of custom direct mapping of kernel32, as above, vs interface mapping which is buit-in JNA, and direct mapping seems as don't give any performace benefit. even worse, it perform a little bit slower, which is contradicting statement of direct mapping performace in the documentation

@twall
Copy link
Contributor

twall commented Jun 17, 2016

There's an explicit performance test within the JNA test suite
(PerformanceTest.java) you can examine and run.

The JNA tests themselves run in both direct and interface mapping modes.

If you're passing anything other than primitive values and pointers as
arguments, then you run the risk of defeating direct mapping's stack
optimization and triggering additional VM operations to properly set up the
call stack.

On Fri, Jun 17, 2016 at 6:58 AM, boscogh notifications@github.com wrote:

I tested performance of custom direct mapping of kernel32, as above, vs
interface mapping which is buit-in JNA, and direct mapping seems as don't
give any performace benefit. even worse, it perform a little bit slower,
which is contradicting statement of direct mapping performace in the
documentation


You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
#497 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAuMrY8pTjPtgN0S0y1i2ebadPspl3S_ks5qMn2-gaJpZM4F21iU
.

@boscogh
Copy link

boscogh commented Jun 18, 2016

yes, probably the case is an OVERLAPPED structure, which I use.
I tried PerformanceTest, thank you for pointing it out. It seems clearly that interface mapping is the slowest one, and there are also lot of interesting other options

mstyura pushed a commit to mstyura/jna that referenced this issue Sep 9, 2024
…ava-native-access#497)

Motivation:

Quiche added support for key updates, which are required for long living connections. Lets use the version that added support

Modifications:

Update to 3b1e5b21977d5b4838362c460444dc758487397c

Result:

No more issues with long living connections
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants