7 messages in net.java.dev.jna.usersRe: [jna-users] Memory allocated for ...
FromSent OnAttachments
Mike PilsburySep 16, 2008 6:52 am 
Timothy WallSep 16, 2008 7:05 am 
Mike PilsburySep 16, 2008 7:26 am 
Mike PilsburySep 17, 2008 1:38 am 
Timothy WallSep 17, 2008 5:23 am 
Mike PilsburySep 17, 2008 6:27 am 
Timothy WallSep 17, 2008 7:11 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [jna-users] Memory allocated for a structureActions...
From:Mike Pilsbury (mike@gmail.com)
Date:Sep 17, 2008 6:27:07 am
List:net.java.dev.jna.users

I'd tried ByteBuffer.wrap(), but it didn't work. Presumably because that creates a non-direct buffer.

Having looked at the javadoc for Memory, it does indeed appear to be just what I should be using. Thanks for the pointer [sic].

Sorry for the dumb questions regarding stuff that is covered in the documentation. Having read the docs several times, I think that I'm finally getting it.

On Wed, Sep 17, 2008 at 1:24 PM, Timothy Wall <twa@users.sf.net> wrote:

You should probably use com.sun.jna.Memory instead for a long-lived buffer. You can also use a direct NIO Buffer, but the usage is less straightforward.

There's a note on this at https://jna.dev.java.net/nonav/javadoc/overview-summary.html#arrays.

On Sep 17, 2008, at 4:38 AM, Mike Pilsbury wrote:

It turns out that the problem wasn't with the structure but with another

another argument to the native methods. It was a block of memory that the native method declared as LPCVOID (effectively *void), for which I was using a byte[]. These are the method signatures:

BOOL WINAPI WriteFile( __in HANDLE hFile, __in LPCVOID lpBuffer, __in DWORD nNumberOfBytesToWrite, __out_opt LPDWORD lpNumberOfBytesWritten, __inout_opt LPOVERLAPPED lpOverlapped );

boolean WriteFileA( int file, byte[] buffer, int bytesToWrite, IntByReference bytesWritten, OVERLAPPED overlapped );

This would have been fine, if I wasn't doing overlapped (non-blocking) IO. The memory allocated for the buffer argument being freed on return from the call is not good, as the IO won't necessarily have completed. So I was getting inconsistent behaviour.

My solution was to wrap the byte[] in a structure, that is kept in scope until the IO completes.

class Data extends Structure { byte[] data;

Data(byte[] data) { this.data = data; } }

void func(byte data) { Data buffer = new Data(data); WriteFileA(file, buffer, bytesToWrite, bytesWritten, overlapped); . . // Wait for IO to complete. WaitForSingleObject(...) }

It works, but I wonder if it's a good solution. Is there a better way of ensuring that the allocated memory stays around long enough?

On Tue, Sep 16, 2008 at 3:26 PM, Mike Pilsbury <mike@gmail.com> wrote: Thanks. That's pretty much what I thought, but it's good to have it confirmed. At least I can eliminate it as a potential cause of my problem.

On Tue, Sep 16, 2008 at 3:06 PM, Timothy Wall <twal@dev.java.net> wrote:

On Sep 16, 2008, at 9:52 AM, Mike Pilsbury wrote:

When the code below is executed, will the same area of memory be used for the structure in both method calls? Or will a fresh block be allocated for each call?

{ MyStructure s = new MyStructure(); // extends Structure

This allocates a block the size of the structure, which is associated with "s" until either "useMemory" is called with a different block or the object is GC'd.

... native_1(s); native_2(s); }

If different areas, then it may explain some weirdness I'm experiencing. In which case, how can I ensure that the same area of memory is used?

If it will use the same area, then I'll have to look for another reason for the strange behaviour.

Note that implicit calls to Structure.write and Structure.read are before and after native invocations, respectively.