15 messages in net.java.dev.jna.usersRe: [jna-users] Non-direct Buffer is ...
FromSent OnAttachments
Drayton BrownMar 11, 2009 9:22 am 
Daniel KaufmannMar 11, 2009 6:59 pm 
Drayton BrownMar 12, 2009 5:33 am 
Daniel KaufmannMar 12, 2009 3:05 pm 
Drayton BrownMar 13, 2009 3:28 am 
Drayton BrownMar 20, 2009 2:55 am 
Drayton BrownMar 20, 2009 4:09 am 
Timothy WallMar 20, 2009 6:03 am 
Drayton BrownMar 20, 2009 7:28 am 
Drayton BrownMar 20, 2009 8:42 am 
Timothy WallMar 20, 2009 9:25 am 
Drayton BrownMar 20, 2009 2:22 pm 
Drayton BrownMar 23, 2009 9:25 am 
Timothy WallMar 23, 2009 11:10 am 
DraytonMar 23, 2009 11:47 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] Non-direct Buffer is not supported?Actions...
From:Drayton Brown (dray@gmail.com)
Date:Mar 20, 2009 7:28:56 am
List:net.java.dev.jna.users

Thanks Timothy! That worked like a charm!

Regards Drayton

2009/3/20 Timothy Wall <twal@dev.java.net>

Methods are looked up by function name, not by parameter or return value. Use a symbol dump tool (depends.exe on w32 or nm on linux or otool on osx) to see the symbols actually exported by your library.

If you see "_MethodName" in the C header, it may be masked by a #define, or it may be mangled by the compiler and/or linker. For example, if you use the stdcall calling convention on windows, function names have an "@NN" appended, where "NN" indicates the number of bytes of arguments to the function.

On Mar 20, 2009, at 5:55 AM, Drayton Brown wrote:

Hi all

Could someone please clarify how to map method names that have an underscore ( '_' ) as the first character?

The C function is something like this: int _MethodName( ... )

and I'm mapping it as follows in my JNA interface: public int _MethodName( ... )

In other words I'm not changing the method name at all, but I still get the following error: Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function '_MethodName'

Could someone let me know if the underscore is a special character in this case? Or is it possible that I've mapped one of the parameters incorrectly and so JNA is unable to match the function signature? (although I don't think this is the case)

Thanks in advance for any help, its much appreciated!

Regards Drayton

2009/3/13 Drayton Brown <dray@gmail.com> Thanks Daniel your help has been most useful!

I believe that option 2 has worked out for me, although I think I will look into the direct buffer information you passed on as I believe I may be able to get some performance gains from it, as you expressed earlier.

Thanks once again,

Regards Drayton

2009/3/12 Daniel Kaufmann <dani@gmail.com> Please check ByteBuffer javadoc for more information regarding Direct and Non-Direct Buffers. ( http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html) wrap creates a non direct Buffer with the passed byte array a the backing array (meaning that when you read/write the buffer you are reading/writing the array. Use ByteBuffer.allocateDirect to create a direct buffer. Then use one of the put methods of ByteBuffer to write to the buffer. After checking jna documentation I believe, option 3 was not correct. From jna docs: "Primitive arrays and structures as members of a structure are overlaid on the parent structure memory." so it is not converted to a pointer that is what you need. Option 4 seem not to be supported, from the exception you are getting. Regarding the size of the image just try to print bytes.length. The memory should have that size, since that is the parameter you pass to the constructor.

Regards, Daniel

On Thu, Mar 12, 2009 at 9:34 AM, Drayton Brown <dray@gmail.com> wrote: Thanks for your timely response Daniel!

I have tried a couple of your solutions already and I thought I'd give some feedback on them, in anticipation that I may get some more help :)

Option 1:

I thought this is what I was doing in my orriginal post? Could someone possibly show me what I'm doing wrong? How does one create this direct buffer, if not by using ByteBuffer?

Option 2:

I change the JNA interface to the C stucture to the following:

public static class RE_IMAGE extends Structure { ... public Pointer data; ... }

I passed in the data as follows:

//We have to pass in a pointer to the data... ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); Memory memory = new Memory(bytes.length); memory.write(0l, bytes, 0, ((Long)memory.getSize()).intValue()); reImage.data = memory;

This option is showing some promise, in that the method I call when I pass in the RE_IMAGE is executed. No Java exception is thrown with this option. However the method returns an error code stating that an invalid parameter has been passed in. I do print out the structure just before the method is executed and reImage.data is shown as follows:

Pointer data@28=allocated@0x9c36eb0 (132440 bytes)

which seems a bit small, since its a 1Mb image that I'm passing in...

As I cannot prove that the error is caused by the Memory object in this case, I'm going to continue to tinker with my implementation, hopfully I'll get lucky!

Also I'm looking into creating a MemoryOutputStream as Daniel surgested, hopefully this will the application faster, which would be really helpful!

Option 3:

I change the JNA interface to the C stucture to the following:

public static class RE_IMAGE extends Structure { ... public byte[] data; ... }

I passed in the data as follows:

RedEye.RE_IMAGE reImage = new RedEye.RE_IMAGE(); ... //We have to pass in a pointer to the data... ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); reImage.data = bytes;

But unfortunately I got the following exception:

Exception in thread "main" java.lang.IllegalStateException: Array fields must be initialized at com.sun.jna.Structure.calculateSize(Structure.java:911) at com.sun.jna.Structure.allocateMemory(Structure.java:219) at com.sun.jna.Structure.ensureAllocated(Structure.java:211) at com.sun.jna.Structure.size(Structure.java:248) at jredeye.Main.main(Main.java:45)

I would take a guess that this may work if I could initialize the array in the RE_IMAGE class, but unfortunately I'm not aware of the size the array needs to be at compile time, and I expect the size will vary greatly at execution time.

Option 4:

I change the JNA interface to the C stucture to the following:

public static class RE_IMAGE extends Structure { ... public Buffer data; ... }

I passed in the data as follows:

RedEye.RE_IMAGE reImage = new RedEye.RE_IMAGE(); ... //We have to pass in a pointer to the data... ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); reImage.data = ByteBuffer.wrap(bytes);

But unfortunately I got the following exception:

Exception in thread "main" java.lang.IllegalArgumentException: the type "java.nio.Buffer" is not supported as a structure field: at com.sun.jna.Structure.getNativeSize(Structure.java:1068) at com.sun.jna.Structure.calculateSize(Structure.java:945) at com.sun.jna.Structure.allocateMemory(Structure.java:219) at com.sun.jna.Structure.ensureAllocated(Structure.java:211) at com.sun.jna.Structure.size(Structure.java:248) at jredeye.Main.main(Main.java:45)

Once again thanks for the help so far, at least I have seem to have a semi-promising lead... If anyone has any more information that may be useful to me, it would be much appreciated.

regards Drayton

2009/3/12 Daniel Kaufmann <dani@gmail.com>

As expected from the method name it indeed does not work for non direct buffers. Since your buffer is backended by a byte array it will not work. Java arrays may not be continuous in memory, so you can't get a pointer to a continuous array as expected by the native code. So you have the following options: • Copy the data to a direct buffer and then get the address • Copy the data to a JNA Memory object and then get the address. • Change reImage.data type to be an array instead of a Pointer. I am not 100% sure this works, but I think so. The data might be copied to an array and then copied back in the native code if the array is non continous. • Change reImage.data type to be a Buffer instead of a Pointer. I believe even non direct buffer are supported in this case but not sure. The data might be copied to an array and then copied back in the native code if the array is non continous. For options 1 and 2 you can avoid copying the data by implementing an OutputStream that is backended by a direct buffer or a JNA Memory object instead of using ByteArrayOutputStream.

Regards, Daniel

On Wed, Mar 11, 2009 at 1:22 PM, Drayton Brown <dray@gmail.com> wrote: Hello all...

I've been working on trying to access a linux shared object from java for the last two weeks. Its my first time using JNA, and its been a reletively good experience. I believe that once I've solved this final problem, I will have completed the task I'm trying to do. As things are becoming quite urgent I would greatly appreciate a timely response.

This is the structure I'm having problems with:

typedef struct {

...

/** Pointer to the first scan line of the image. In case of planar format it is a pointer to an array of pointers to separate planes. */ void* Data;

...

} RE_IMAGE;

I've coded this as follows:

public interface RedEye extends Library {

public static class RE_IMAGE extends Structure {

...

public Pointer data;

...

}

}

And I'm using it like this:

RedEye.RE_IMAGE reImage = new RedEye.RE_IMAGE();

... //We have to pass in a pointer to the data... ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(image_input, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); Buffer buffer = (Buffer) byteBuffer; reImage.data = Native.getDirectBufferPointer(buffer); ...

Unfortunately this is throwing the following exception:

Exception in thread "main" java.lang.IllegalArgumentException: Non-direct Buffer is not supported at com.sun.jna.Native.getDirectBufferPointer(Native Method) at jredeye.Main.main(Main.java:60)

If any further detail is required, please feel free to ask. Any help or input on this would be greatly appreciated.

Regards Drayton