6 messages in net.java.dev.jna.usersRe: [jna-users] no values read after ...
FromSent OnAttachments
Kratzer, HeinrichOct 25, 2007 12:35 pm 
Timothy WallOct 25, 2007 3:14 pm 
Kratzer, HeinrichOct 26, 2007 2:02 am 
Kratzer, HeinrichOct 26, 2007 3:43 am 
Timothy WallOct 26, 2007 5:24 am 
Timothy WallOct 26, 2007 5:28 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] no values read after call from a structure with bytebuffer insiActions...
From:Timothy Wall (twal@dev.java.net)
Date:Oct 26, 2007 5:28:20 am
List:net.java.dev.jna.users

You should grab a manual that explains how C structures are laid out in memory. In short, your pointer occupies 4 bytes and is followed in memory immediately by the three other fields. When you allocate a byte[] in the Structure, JNA interprets that to mean you want those bytes contiguous in memory within the Structure, so instead of a 4 byte pointer you have N bytes.

As I suggested previously, make the field a Pointer and assign it a Memory object of the appropriate size. I'll see about fixing Buffer support within Structures.

On Oct 26, 2007, at 6:43 AM, Kratzer, Heinrich wrote:

Hallo Timothy,

i can report some kind of progress.

First i modified my structure (inspired by com.sun.jna.examples.win32.GDI32.java#RGNDATA)

- it is not something really new

public class STImage extends Structure {

/** pixels buffer : must be allocated by the caller */

public byte[] pbyBuffer;

/** Number of columns */

public short wNbCol;

/** Number of Rows */

public short wNbRow;

/** pixels buffer size (in bytes) : must be initialized by the caller to IMAGE_SIZE */

public int dwBufferSize;

public STImage() {

super(Structure.CALCULATE_SIZE, Structure.ALIGN_DEFAULT);

pbyBuffer = new byte[BiometricDll.IMAGE_SIZE];

dwBufferSize = pbyBuffer.length;

// write some testpattern inside

for (int idx = 0; idx < pbyBuffer.length; idx++) {

pbyBuffer[idx] = (byte)0xFF;

}

allocateMemory();

}

public void write() {

// avoid reading buffer until we know how long it is

super.write();

int idx = 0;

for (int offset = idx; (idx - offset) < dwBufferSize; idx++) {

getPointer().setByte(idx, (byte) (pbyBuffer[idx - offset] & 0xFF));

}

}

public void useMemory(Pointer m) {

super.useMemory(m);

}

}

Second i changed the signature of function ‘GetImage’ replacing the Pointer by PointerByReference (Don’t ask how i got this idea):

int GetImage(

PointerByReference pstImage,

LPID3BIO_STATUS_ROUTINE lpUpdateFunc,

Pointer pvUpdateContext,

LPID3BIO_COMPLETION_ROUTINE lpCompletionRoutine,

Pointer pvCompletionContext);

Now i receive image data in callback-function – at least there are any new data – but there is a new trouble…

No data has been set into the other three variables wNbCol, wNbRow, dwBufferSize.

What should i do, to get the data ? (i need them because i want to view the picture!)

I read the data calling the following code:

STImage fpImage = null;

STImage newImage = null;

PointerByReference refImage = null;

fpImage = fpPane.fpImage;

refImage = fpPane.refImage;

fpImage.read();

newImage = new STImage();

newImage.useMemory (refImage.getPointer(0));

fpImage and newImage have the same content .

There is a dump of the structure STImage with new data inside (dwBufferSize should bet he actual size not the initial 128400/90f50100, wNbCol and wNbRow should be something between 300 and 450):

GetImage:LPID3BIO_COMPLETION_ROUTINE dwBufferSize=128400, wNbRow=0, wNbCol=0

GetImage:LPID3BIO_COMPLETION_ROUTINE size=128408

GetImage:LPID3BIO_COMPLETION_ROUTINE Pointer SIZE=4, native@0xb580048

structure class=de.gematik.biometric.certis.STImage, lenght=128408, hashcode=190316616, pointer=native@0xb580048

0: [80808080 80888899] [88888899 88998888] [88888888 88888888] [88777788 77887777] [77776677 66776666] [66666655 55666655] [55555544 44444455] [44445544 33333322

40: [22333322 22221111] [11110000 00000000] [00000000 00000000] [00000000 00001111] [22222211 11112211] [00000000 00000000] [00000000 00000000] [00000000 00111111

80: [00000000 22000000] [00000000 00000000] [00000000 00000000] [00001111 11110011] [11111122 22222222] [22221122 22222222] [22112233 33443344] [44444444 44444455

c0: [55556655 55556666] [66666666 66666666] [66667766 77777777] [77777777 77777777] [77777777 77777777] [77888888 88887788] [77887788 88888888] [88888888 88888888

100: [88888888 88888888] [88888888 99888888] [88888888 99888888] [88888888 88808080] [80808080 80808080] [80808080 80808080] [80998888 88888899] [88889977 88888888

140: [........ ........]

1f4c0: [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080

1f500: [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080

1f540: [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080] [80808080 80808080

1f580: [80808080 80808080] [80808080 80808080] [00000000 90f50100]

Thanks a lot in advance!

Heinrich Kratzer

Telefon: (030) 400 / 41-250 Telefax: (030) 400 / 41-111 E-Mail: hein@gematik.de www.gematik.de

gematik Gesellschaft für Telematikanwendungen der Gesundheitskarte mbH Friedrichstraße 136 10117 Berlin Amtsgericht Berlin-Charlottenburg HRB 96351 B Geschäftsführer Peter Bonerz, Dirk Drees

Von: Kratzer, Heinrich [mailto:Hein@gematik.de] Gesendet: Freitag, 26. Oktober 2007 11:02 An: use@jna.dev.java.net Betreff: [jna-users] no values read after call from a structure with bytebuffer inside

Hallo Timothy,

thanks a lot for your quickly replay.

I tried your suggest (see below) – but it do not work.

Please see the changed structure:

public class STImage extends Structure {

/** pixels buffer : must be allocated by the caller */

public Buffer pbyBuffer = ByteBuffer.wrap(new byte[IMAGE_SIZE]);

/** Number of columns */

public short wNbCol;

/** Number of Rows */

public short wNbRow;

/** pixels buffer size (in bytes) : must be initialized by the caller to IMAGE_SIZE */

public int dwBufferSize = IMAGE_SIZE;

}

I used the structure like this:

fpPane.fpImage = new STImage();

int result = libSync.GetImage (fpPane.fpImage.getPointer(), procGetImageStatus, context.getPointer (), procImageAvailable, context.getPointer());

executing ‘new STImage’ i produces the following exception:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Native type undefined for class java.nio.ByteBuffer

at com.sun.jna.Structure.getNativeSize(Structure.java:737)

at com.sun.jna.Structure.getNativeSize(Structure.java:756)

at com.sun.jna.Structure.calculateSize(Structure.java:639)

at com.sun.jna.Structure.allocateMemory(Structure.java: 172)

at com.sun.jna.Structure.<init>(Structure.java:91)

at com.sun.jna.Structure.<init>(Structure.java:85)

at com.sun.jna.Structure.<init>(Structure.java:81)

at de.gematik.biometric.certis.STImage.<init> (STImage.java:35)

It seems, that the Structure can not allocate the Memory of a field of type Buffer.

(I am using the JNA from SVN:HEAD).

What goes wrong? Have i misunderstood your hint?

Thanks in advance for your help.

Heinrich Kratzer

Date: Thu, 25 Oct 2007 18:14:43 -0400From: Timothy Wall <twal@dev.java.net>Content-type: text/plain; charset=WINDOWS-1252; delsp=yes; format=flowedSubject: [jna-users] no values read after call from a structure with bytebuffer insi See comments below. Basically, your structure definition on the Java side is incorrect. On Oct 25, 2007, at 3:36 PM, Kratzer, Heinrich wrote: > Hallo,> > The function i use from native library takes as first argument a > pointer to a structure, as second a callback function, … .> It looks like this:> /**> > * ID3BIO_EXPORTS_API DWORD __cdecl GetImage(> > * STImage* pstImage,> > * LPID3BIO_STATUS_ROUTINE lpUpdateFunc,>

* PVOID pvUpdateContext,> > *

LPID3BIO_COMPLETION_ROUTINE lpCompletionRoutine,> > * PVOID pvCompletionContext);> > */> > int GetImage(>

Pointer pstImage,> >

LPID3BIO_STATUS_ROUTINE lpUpdateFunc,> > Pointer pvUpdateContext,> > LPID3BIO_COMPLETION_ROUTINE lpCompletionRoutine,> > Pointer pvCompletionContext);> > pstImage is a pointer to the structure, which should receive the > data. After completion the function calls assynchron the callback > function ‚lpUpdateFunc’, which works really fine. Using the context > i can access the structure. But i can not access any new data (The > data seem to be unchanged, but they are definitly not). When i > preset the buffer bevor call with ‚FF’ the VM crashes. The > behaviour is a little bit unpredictable, sometimes ‚GetImage’ > returns an error, sometimes VM crashes or nothing happens. What i > make wrong?> > Here the structure:> /**> * typedef struct> * {> * // pixels buffer : must be allocated by the caller> * BYTE* pbyBuffer;> * // Number of columns> * WORD wNbCol;> *> * // Number of Rows> * WORD wNbRow;> *> * // pixels buffer size (in bytes) : must be initialized by > the caller to IMAGE_SIZE> * DWORD dwBufferSize;> *> * } STImage, *PSTImage;> */> public class STImage extends Structure {> /** pixels buffer : must be allocated by the caller */> // public byte[] pbyBuffer = new byte[IMAGE_SIZE];> public byte[] pbyBuffer;This field needs to be a Pointer or Buffer. Using a primitive array makes the structure allocate memory for it in- line, making your structure as large as your buffer.> > /** Number of columns */> public short wNbCol;> > /** Number of Rows */> public short wNbRow;> > /** pixels buffer size (in bytes) : must be initialized by the > caller to IMAGE_SIZE (public final int IMAGE_SIZE = (int)128400) */> public int dwBufferSize;> > public STImage() {> super (Structure.CALCULATE_SIZE, Structure.ALIGN_MSVC);> ALIGN_MSVC is the default on windows, so the argument is redundant here.

pbyBuffer = new byte[IMAGE_SIZE];>

dwBufferSize = pbyBuffer.length;Instead, use ByteBuffer.wrap(new byte[IMAGE_SIZE]; it's also better style to initialize the fields inline rather than in the ctor, unless you need to do some complex initialization. If the size can't be calculated by the Structure ctor, size calculation and memory allocation are deferred until the structure is actually passed to a function, so in most cases you don't have to do it explicitly in your subclass ctor.