

![]() | Start a set with this search |
![]() | Include this search in one of my sets |
![]() | Exclude this search from one of my sets |
![]() | Permalink to these results Paste this link in email or IM: |
| Atom feed for tracking future search results Paste this URL into your reader: |
6 messages in net.java.dev.jna.usersRe: [jna-users] Structure mapping que...| From | Sent On | Attachments |
|---|---|---|
| Steve Newell | Jul 30, 2008 11:05 am | |
| Michael Brewer-Davis | Jul 30, 2008 11:42 am | |
| Timothy Wall | Jul 30, 2008 11:48 am | |
| Steve Newell | Jul 30, 2008 12:34 pm | |
| Timothy Wall | Jul 30, 2008 2:48 pm | |
| Steve Newell | Jul 31, 2008 12:33 pm |

![]() | Permalink for this message Paste this link in email or IM: |
![]() | Permalink for this thread Paste this link in email or IM: |
| Atom feed for this thread Paste this URL into your reader: |
| Subject: | Re: [jna-users] Structure mapping question | Actions... |
|---|---|---|
| From: | Steve Newell (newe...@gmail.com) | |
| Date: | Jul 30, 2008 12:34:05 pm | |
| List: | net.java.dev.jna.users | |
Perfect. Seems to work now. However, I have a new problem.
The method I am calling has the following signature in C:
int DllExport FindMatchingDeletedFiles( LPCWSTR szDirectory, PFileSignature fileSignatures, int numFileSignatures, PPDeletedFileHandle fileHandles );
I mapped it to the following java code:
public int FindMatchingDeletedFiles( WString szDirectory, FileSignature[] fileSignatures, int numFileSignatures, PointerByReference fileHandles );
To call it, I create a PointerByReference and pass it as the final parameter.
The return value should be the number of DeletedFileHandles that the final parameter are pointing to. My problems are: 1. I'm not sure that's the right way to call this 2. The pointer comes back, and it looks correct, but when I try to convert it to an array, I get problems. The way I am doing this is:
DeletedFileHandleW delFiles = new DeletedFileHandleW( fileHandles.getPointer() );
public class DeletedFileHandleW extends Structure { public WString filename; public WString directory; public int condition; public long create_date; public long access_date; public long modify_date; public int length; public Pointer contentsPtr;
protected byte[] contents;
public DeletedFileHandleW( Pointer p ) { super(); useMemory( p ); read();
} }
When I make this call, I get:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Bounds exceeds available space : size=4, offset=48 at com.sun.jna.Memory.boundsCheck(Memory.java:149) at com.sun.jna.Memory.share(Memory.java:90) at com.sun.jna.Structure.useMemory(Structure.java:192) at com.sun.jna.Structure.useMemory(Structure.java:183) at com.surfrecon.jna.windows.undelete.Undelete $DeletedFileHandleW.<init>(Undelete.java:168) at test.com.surfrecon.jna.windows.undelete.Driver.main(Driver.java:25)
Suggestions?
Thanks.
On Jul 30, 2008, at 12:48 PM, Timothy Wall wrote:
On Jul 30, 2008, at 2:06 PM, Steve Newell wrote:
I have the following C structs:
typedef struct ByteSignature { int offset; int length; PBYTE signature; } ByteSignature;
typedef struct FileSignature { char* mimeType; // NULL terminated string int numSignatures; // number of ByteSignatures in the signatures array ByteSignature* signatures; // array of ByteSignatures. There must be at least 1, to be valid. } FileSignature, * PFileSignature, ** PPFileSignature;
FileSignature is allocated and filled by my Java code, and passed to the dll.
I have mapped these two structures as follows:
public class ByteSignature extends Structure { public int offset; public int length; public byte[] signature;
The signature field needs to be a Pointer. Primitive arrays are inlined, which is not what you want.
public ByteSignature() { super(); } public ByteSignature( Pointer p ) { super(); useMemory( p ); read(); } public ByteSignature( int offset, byte... byteValues ) { super(); this.offset = offset; this.length = byteValues.length; signature = new byte[ byteValues.length ];
for( int i = 0; i < byteValues.length; i++ ) { signature[ i ] = byteValues[ i ]; } } }
You probably want to allocate the memory yourself here for "signature", and use Pointer methods to set its contents.
public class FileSignature extends Structure { public String mimeType; public int numSignatures; public ByteSignature[] signatures;
This needs to be a pointer, since nested structures are inlined. You can also make the field implement Structure.ByReference to force the field to be treated as a pointer rather than by value.
e.g.
class ByteSignature extends Structure { class ByReference extends ByteSignature implements Structure.ByReference { } }
ByteSignature[] bsa = new ByteSignature.ByReference().toArray(size); s.signatures = bsa[0];
public FileSignature() { super(); } public FileSignature( Pointer p ) { super(); useMemory( p ); read(); } }
The function I am attempting to call looks like this:
public int FindMatchingDeletedFiles( WString szDirectory, FileSignature[] fileSignatures, int numFileSignatures, PointerByReference fileHandles );
and this is how I am calling it:
public static void main( String[] args ) { Native.setProtected( true );
Undelete undelete = Undelete.INSTANCE;
PointerByReference fileHandles = new PointerByReference();
FileSignature[] signatures = createFileSignatures();
int numFiles = undelete.FindMatchingDeletedFiles( new WString( "C: \\" ), signatures, signatures.length, fileHandles );
for( int i = 0; i < numFiles; i++ ) { ... } }
However, when I run this, I get the following error:
Exception in thread "main" java.lang.IllegalStateException: Array fields must be initialized
This error should go away once you eliminate primitive array fields as described above.







