Re: New JNA issue not sure where to go from here for debug

153 views
Skip to first unread message

Timothy Wall

unread,
May 9, 2013, 10:03:06 PM5/9/13
to Mark Riley, jna-...@googlegroups.com
Dump the class loader and classpath in both cases to verify that you're really using the same JNA code in both cases and not inadvertently picking up a different version (from an IDE or elsewhere in your environment).

On May 9, 2013, at 4:42 PM, Mark Riley wrote:

> Timothy,
>
> It may be best to explain to you how exactly I’m trying to use JNA and my libraries. And then explain my issue.
>
> The product we create is a graphical panel with on board memory and such. I think Geertjan summed up what we do fairly well in his blog this week (https://blogs.oracle.com/geertjan/entry/graphic_touch_panel_system_development)
>
> We have been using serial communications to transfer code to the board. We are currently in the process of changing the communication from RXTX serial to raw usb using WINUSB. We created a C program that parses command line arguments and connect to our board using WINUSB; it works great. Our development and testing software are all created in Java using Netbeans platforms. The easiest solution we found was to use JNI or JNA to use our pre-existing C code to communicate to winusb. We turned our C program into a DLL and are in the process of creating JNA to access the library.
>
> So there are going to be 3 parts to doing this:
> · DLL Created from C code that accesses WINUSB (Completed)
> · A library (JAR File) that contains the DLL’s and the JNA code to access the DLL functions. This Library will also include code for common tasks: Finding devices, Reading and Writing information to and from the boards.
> · Our Java application(s) that need to access the JAR file in order to communicate to our boards
>
> So far JNA has been very straight forward and wonderful to work with. I can find the devices and write information to the boards through this JAR library with no issues. I’m trying to add the capability of reading the serial numbers from our board and this is where I’m running into the most issues.
>
> And obvious by my e-mails and posts on stack over flow I’m having issues with the data stored in the structures. I’ve made some progress today and created a test case. This test case works after finding and solving an issue found with alignments. It works both in the JNA project its self and it works as a library call from the JAR file when plugged into another project. Since I found an issue from thetest case I was hoping it would solve my issue with pulling the serial number directly from the board. First I tested it from within the JNA project its self and to my relief it worked.
>
> Ser: "205140000000009"
> SerName: "0205140000000009 "
> hw: "a8130e0215153024"
> hwName: "A8130E0215153024 "
> oem: "ffffffffffffffff"
> oemName: "FFFFFFFFFFFFFFFF "
>
> I went ahead and packaged the JNA project as a JAR an plugged it into my application calling the same methods that I has called from the test directly with the JNA project. The results were familiar to the issues I was previously had. The values were incorrect again.
>
> Ser: "3030343135303230"
> SerName: "00000009 $0 "
> hw: "3230453033313841"
> hwName: "15153024 ÿÿÿÿ"
> oem: "4646464646464646"
> oemName: "FFFFFFFF "
>
> The only difference between the 2 results was that one was called from within the JNA project its self, and the other was called using the library created from the JNA project.
>
> So I’m at a bit of a loss here. I’m not sure what to provide to assist into looking into the issue.
>
> Thanks,
> Mark Riley
>
>

Neil C Smith

unread,
May 10, 2013, 4:22:43 AM5/10/13
to jna-...@googlegroups.com, Mark Riley
Hi Mark,

To jump in slightly as someone also working with the NetBeans
platform, what version of the platform are you using and which version
of JNA? The NetBeans platform also ships with JNA, and possibly an
older version than you're using. I wrote a couple of blog posts about
using an updated JNA with NetBeans platform prior to 7.2 [1][2]. If
you're on NB7.2+ then you can probably get away with disabling the
built-in JNA if you forego certain modules (eg. the platform specific
master filesystem modules). Unfortunately, getting the platform to
work with JNA 3.5+ in the way outlined in my blog posts may be
difficult due to the structure field changes.

Enjoyed reading Geertjan's blog post about your project yesterday.

Best wishes,

Neil

[1] http://praxisintermedia.wordpress.com/2012/01/04/jna-3-4-0-on-the-netbeans-platform/
[2] http://praxisintermedia.wordpress.com/2012/06/21/jna-3-4-netbeans-revised/
--
Neil C Smith
Artist : Technologist : Adviser
http://neilcsmith.net

Praxis LIVE - open-source, graphical environment for rapid development
of intermedia performance tools, projections and interactive spaces -
http://code.google.com/p/praxis

OpenEye - specialist web solutions for the cultural, education,
charitable and local government sectors - http://openeye.info
> --
> You received this message because you are subscribed to the Google Groups "Java Native Access" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Timothy Wall

unread,
May 10, 2013, 7:26:22 AM5/10/13
to jna-...@googlegroups.com, Mark Riley
The upcoming 3.6 release (with bits in 3.5.2) make it easier to have multiple versions of JNA loaded at the same time, namely by enabling them to be loaded in different class loaders.

Previously JNA depended on the primordial class loader to load its native bits, but 3.6 allows you to specify a different one, and also defaults to loading its own JNI library with the same class loader that loaded the Native class.

Neil C Smith

unread,
May 10, 2013, 12:03:26 PM5/10/13
to Mark Riley, jna-...@googlegroups.com
Mark,

Not sure the blog posts will help with that combination. I'd suggest
just disabling the JNA module in the platform cluster, and anything
that depends on it, and seeing if that fixes your initial problem. Of
course, if you end up disabling something you're relying on elsewhere
you may be in a catch-22.

Good luck with it,

Neil

On 10 May 2013 16:57, Mark Riley <mark....@seriousintegrated.com> wrote:
> Neil,
>
> I'm using the head rev. from 2 days ago I think it's still 3.5.x. I'm using Netbeans 7.2.1 currently. I'll take a look at your blog entry and investigate possible JNA issues with the platform. I suspect this is the issue I maybe seeing.
>
> Thanks,
> Mark

Mark Riley

unread,
May 10, 2013, 12:09:07 PM5/10/13
to Neil C Smith, jna-...@googlegroups.com
I've disabled Native Access, and all of the Master File System modules and the issue still persists. Do you know if there are any other modules? I'll google for a bit of information as well.

Neil C Smith

unread,
May 10, 2013, 12:13:20 PM5/10/13
to jna-...@googlegroups.com
Have you disabled the JNA module in platform though? Sorry if that's
an obvious question! :-)

N

Mark Riley

unread,
May 10, 2013, 12:17:25 PM5/10/13
to Timothy Wall, jna-...@googlegroups.com
Timothy,

When I call it from the JNA project I get

sun.misc.Launcher$AppClassLoader@4cdac8
[file:/C:/Users/Mark%20Riley/Documents/mer-rawusb/ide/Libraries/SHIPFlashProgrammer/lib/platform-3.5.2.jar, file:/C:/Users/Mark%20Riley/Documents/mer-rawusb/ide/Libraries/SHIPFlashProgrammer/lib/, file:/C:/Users/Mark%20Riley/Documents/mer-rawusb/ide/Libraries/SHIPFlashProgrammer/lib/jna-3.5.2.jar, file:/C:/Users/Mark%20Riley/Documents/mer-rawusb/ide/Libraries/SHIPFlashProgrammer/build/classes/]

So this appears to be using thr right JNA file. When I called it from the Netbean's Platform as a wrapped JAR I get:

ModuleCL@5622ca71[com.seriousintegrated.ship.flashprogrammer]

Java.lang.ClassCastException: org.netbeans.StandardModule$OneModuleClassLoader cannot be cast to java.net.URLClassLoader
at shipflashprogrammer.SHIPFlashProgrammer.getUsbDevices(SHIPFlashProgrammer.java:67)
at com.seriousintegrated.ship.flashprogrammer.OutfitTopComponent.refreashButtonActionPerformed(OutfitTopComponent.java:199)
at com.seriousintegrated.ship.flashprogrammer.OutfitTopComponent.access$000(OutfitTopComponent.jav

I'm not sure if Netbean'ss Platforms will let me get the classloader URL's.

I do suspect you may be correct that I'm pulling another JNA version. This is sort of reinforced by Neil's e-mail as well. It seems I may need to research Netbean's platform and its usage of JNA.

Thanks,
Mark



-----Original Message-----
From: Timothy Wall [mailto:twal...@java.net]
Sent: Thursday, May 09, 2013 7:03 PM
To: Mark Riley
Cc: jna-...@googlegroups.com
Subject: Re: New JNA issue not sure where to go from here for debug

Mark Riley

unread,
May 10, 2013, 12:46:31 PM5/10/13
to jna-...@googlegroups.com
I did not turn off JNA. I turned off Native Access and didn't look for JNA. How silly.

Regardless the issue still remains even with JNA, Native Access, and all of the Master File System modules all disabled.

Mark Riley

unread,
May 10, 2013, 1:05:04 PM5/10/13
to jna-...@googlegroups.com
The issue is definitely Netbeans Platform.

I created a standard java project and used the same JAR file and got the values I expected. I'll shoot the Netbeans platform mailing list an e-mail and see if there is a solution on their end.

Thanks for helping me isolate the issue!

Mark Riley

unread,
May 13, 2013, 7:47:41 PM5/13/13
to jna-...@googlegroups.com
I made a bit of a break through today. I find it a bit silly since this is something I swore I tested much earlier.

I made my project use 32bit Java instead of 64 bit. Output was the expected output. I went back into my C code and I created a 64Bit executable and the output is also okay.

The issue seems to only happen when I use the JNA project using a 64bit java. Is this a known issue? Is there anything I need to specifically do for a project using JNA to work using 64 bit?

Timothy Wall

unread,
May 13, 2013, 8:57:56 PM5/13/13
to jna-...@googlegroups.com
Maybe the netbeans 32-bit libjnidispatch.so is OK and the 64-bit one is not? I believe they do have both in the classpath/resource path.

Mark Riley

unread,
May 13, 2013, 9:15:45 PM5/13/13
to jna-...@googlegroups.com

This was replicated on a non-platform project. So the only JNA used was the one I built a few days ago fun head rev.

Thanks,
Mark

On May 13, 2013 5:58 PM, "Timothy Wall" <twal...@java.net> wrote:
Maybe the netbeans 32-bit libjnidispatch.so is OK and the 64-bit one is not?  I believe they do have both in the classpath/resource path.

On May 13, 2013, at 7:47 PM, Mark Riley wrote:

Timothy Wall

unread,
May 14, 2013, 7:09:33 AM5/14/13
to jna-...@googlegroups.com
don't know what "non-platform project" means.

was the x86-64 native as up-to-date as the 64-bit one? I vaguely recall that at the time I mentioned it, I had only updated the x86 one (x86-64 should also be up to date now).

Mark Riley

unread,
May 14, 2013, 11:48:51 AM5/14/13
to jna-...@googlegroups.com
Sorry, Netbean's JNA is only included in a "Netbean's Platform Project" so when I say non-platform I'm referring to a project that is not created using the Netbean's Platform Project framework.

I went ahead and grabbed head rev and built it but the Issue persists. Tested my C code again and the output is accurate.

I tried the test code I put in where I manually set all the values of the structure and those values are correct. The issue seems to be only when I use JNA to pull the serial from the device when using 64Bit.

Thanks for your help and patience so far,

Timothy Wall

unread,
May 14, 2013, 12:17:06 PM5/14/13
to jna-...@googlegroups.com
Can you capture the essence of the operation in question (pardon my limited attention bandwidth)?

Isolate the flow of data as best you can, e.g.

* call native method
* native method fills in struct
* read struct back on java side

or

* call native method with callback param
* native thread calls callback with data
* read data in java callback

If I can simplify this to a single native->java or java->native handoff, it'll be easier to track down.

If the Java and native sides agree on the size and the layout of the structure/union, then the problem is in the data copy, so I need to know which path is being taken to examine it more closely.

Mark Riley

unread,
May 14, 2013, 5:27:43 PM5/14/13
to jna-...@googlegroups.com
* Call Java Library method GetSN
* Java Library method GetSN Calls Native function Initialize_Device(Confirmed working as intended)
* Java Library method GetSN Calls Native Function SHIP_Bridge(Confirmed working as intended)
* Java Library method GetSN Calls Native Function SHIP_PlatformGetSN passing Array of Union mySN
* Native Function SHIP_PlatformGetSN retrieves Serial Number from Board and Copies it to Union
* Java Library method GetSN returns Array of Union MySN

Hope that is the information you were requesting.

Timothy Wall

unread,
May 15, 2013, 8:24:47 AM5/15/13
to jna-...@googlegroups.com
Might be the array of union. I recently found an issue with the padding of structs/unions on win64 (only on the 3.6 stuff, not older).

Do you get proper values in the first union in the array but not subsequent ones?

Mark Riley

unread,
May 15, 2013, 11:13:32 AM5/15/13
to jna-...@googlegroups.com
All the values seem incorrect.

Expected Memory Dump looks like this:

SHIP_SN(allocated@0x191418d0 (96 bytes) (shared from allocated@0x19141490 (1184 bytes) (shared from auto-allocated@0x19141490 (9472 bytes)))) {
SHIP_SN$field_struct field@0=SHIP_SN$field_struct(auto-allocated@0x1913e7e0 (8 bytes)) {
NativeLong sequence@0=0
byte variant@4=0
byte version@5=0
short pid@6=0
}
SHIP_SN$sn_struct sn@0=SHIP_SN$sn_struct(allocated@0x191418d0 (96 bytes) (shared from allocated@0x191418d0 (96 bytes) (shared from allocated@0x19141490 (1184 bytes) (shared from auto-allocated@0x19141490 (9472 bytes))))) {
long serious@0=205140000000009
byte seriousName[20]@8=[B@fe83e5
long hw@20=a8130e0215153024
byte hwName[20]@28=[B@185477d
long oem@40=ffffffffffffffff
byte oemName[20]@48=[B@1188439
}
}
memory dump
[09000000]
[00140502]
[30323035]
[31343030]
[30303030]
[30303039]
[00000000]
[00000000]
[24301515]
[020e13a8]
[41383133]
[30453032]
[31353135]
[33303234]
[00000000]
[00000000]
[ffffffff]
[ffffffff]
[46464646]
[46464646]
[46464646]
[46464646]
[00000000]
[00000000]

What I am getting is:

SHIP_SN(allocated@0xe1aa9f8 (96 bytes) (shared from allocated@0xe1aa5a0 (1208 bytes) (shared from auto-allocated@0xe1aa5a0 (9664 bytes)))) {
SHIP_SN$field_struct field@0=SHIP_SN$field_struct(auto-allocated@0xe2e83f0 (8 bytes)) {
NativeLong sequence@0=0
byte variant@4=0
byte version@5=0
short pid@6=0
}
SHIP_SN$sn_struct sn@0=SHIP_SN$sn_struct(allocated@0xe1aa9f8 (96 bytes) (shared from allocated@0xe1aa9f8 (96 bytes) (shared from allocated@0xe1aa5a0 (1208 bytes) (shared from auto-allocated@0xe1aa5a0 (9664 bytes))))) {
long serious@0=3030343135303230
byte seriousName[20]@8=[B@479747c9
long hw@20=3230453033313841
byte hwName[20]@28=[B@1cea01d7
long oem@40=4646464646464646
byte oemName[20]@48=[B@471ed915
}
}
memory dump
[30323035]
[31343030]
[30303030]
[30303039]
[00000000]
[00000000]
[24301515]
[020e13a8]
[41383133]
[30453032]
[31353135]
[33303234]
[00000000]
[00000000]
[ffffffff]
[ffffffff]
[46464646]
[46464646]
[46464646]
[46464646]
[00000000]
[00000000]
[00000000]
[00000000]

So in 64Bit I'm completely missing the first 8 bytes:
[09000000]
[00140502]

Mark Riley

unread,
Nov 25, 2013, 12:21:04 PM11/25/13
to jna-...@googlegroups.com
Hello,

I am still getting this issue with JNA 4.0.0 using 64bit java only. 32 Bit woks with no issues.

Timothy Wall

unread,
Nov 27, 2013, 7:55:36 AM11/27/13
to jna-...@googlegroups.com
can you provide the native declarations/definitions side by side with your attempted Java mappings?
thanks

Mark Riley

unread,
Nov 27, 2013, 12:14:56 PM11/27/13
to jna-...@googlegroups.com
Sure.

//Native Declaration
union _SHIP_SN {
struct {
long sequence;
char variant;
char version;
int pid;
} SHIP_PACK field;
struct {
long long serious;
char seriousName[20];
long long hw;
char hwName[20];
long long oem;
char oemName [20];
} sn;
};

typedef union _SHIP_SN SHIP_SN;


//JNA Java Declaration
public class SHIP_SN extends Union {

public field_struct field;
public sn_struct sn;

public static class field_struct extends Structure {

public NativeLong sequence;
public byte variant;
public byte version;
public short pid;

public field_struct() {
super();
}

protected List getFieldOrder() {
return Arrays.asList("sequence", "variant", "version", "pid");
}

public field_struct(NativeLong sequence, byte variant, byte version, short pid) {
super();
this.sequence = sequence;
this.variant = variant;
this.version = version;
this.pid = pid;
}

public static class ByReference extends field_struct implements Structure.ByReference {
};

public static class ByValue extends field_struct implements Structure.ByValue {
};
};

public static class sn_struct extends Structure {

public long serious;
public byte[] seriousName = new byte[20];
public long hw;
public byte[] hwName = new byte[20];
public long oem;
public byte[] oemName = new byte[20];

public sn_struct() {
super();
}

protected List getFieldOrder() {
return Arrays.asList("serious", "seriousName", "hw", "hwName", "oem", "oemName");
}

public sn_struct(long serious, byte[] seriousName, long hw, byte[] hwName, long oem, byte[] oemName) {
super();
this.serious = serious;
if (seriousName.length != this.seriousName.length) {
throw new IllegalArgumentException("Wrong array size !");
}
this.seriousName = seriousName;
this.hw = hw;
if (hwName.length != this.hwName.length) {
throw new IllegalArgumentException("Wrong array size !");
}
this.hwName = hwName;
this.oem = oem;
if (oemName.length != this.oemName.length) {
throw new IllegalArgumentException("Wrong array size !");
}
this.oemName = oemName;
}

public static class ByReference extends sn_struct implements Structure.ByReference {
};

public static class ByValue extends sn_struct implements Structure.ByValue {
};
};

public SHIP_SN() {
super();
}

public SHIP_SN(sn_struct sn) {
super();
this.sn = sn;
setType(sn_struct.class);
}

public SHIP_SN(field_struct field) {
super();
this.field = field;
setType(field_struct.class);
}

public static class ByReference extends SHIP_SN implements Structure.ByReference {
};

public static class ByValue extends SHIP_SN implements Structure.ByValue {
};

Timothy Wall

unread,
Nov 27, 2013, 3:48:04 PM11/27/13
to jna-...@googlegroups.com
“pid” doesn’t match up (native “int” vs Java “short”)

what type of alignment are you *expecting* in these?

On Nov 27, 2013, at 12:14 PM, Mark Riley <mark....@seriousintegrated.com> wrote:

> Sure.
>
> //Native Declaration
> union _SHIP_SN {
> struct {
> long sequence;
> char variant;
> char version;
> int pid;
> } SHIP_PACK field;

“sequence” will be 32 bits or 64 bits. “pid” will likely get some padding in front of it to ensure alignment on a 4-byte boundary.


> struct {
> long long serious;
> char seriousName[20];
> long long hw;
> char hwName[20];
> long long oem;
> char oemName [20];

these char arrays will likely each have 4 bytes padding after each, before the next 64-bit field (aligning on a 64-bit boundary).

What is your native code expecting?

Mark Riley

unread,
Nov 27, 2013, 6:39:36 PM11/27/13
to jna-...@googlegroups.com
Sorry, those use our defines. I made a mistake in changing them in my head.

It should look like:

union _SHIP_SN {
struct {
unsigned long sequence; // unique to each pid+version+variant
unsigned char variant; // platform variant (e.g. SIM205-A00 vs A01; assigned in SIM205.h)
unsigned char version; // major4.minor4 (ex: 0x14 represents version 1.4)
unsigned short pid; // Default USB Product ID of the hardware (ex: SIM205 = 0x0205)
} SHIP_PACK field;
struct {
unsigned long long serious;
unsigned char seriousName [20]; // needs to be 16 digits *plus* the \0, plus 4 byte align ending
unsigned long long hw; // HW serial number (all FF's means not present)
unsigned char hwName [20]; // needs to be 16 digits *plus* the \0, plus 4 byte align ending
unsigned long long oem; // OEM serial number (all FF's means not set)
unsigned char oemName [20]; // needs to be 16 digits *plus* the \0, plus 4 byte align ending
} sn;
};

typedef union _SHIP_SN SHIP_SN;

Timothy Wall

unread,
Nov 27, 2013, 10:38:24 PM11/27/13
to jna-...@googlegroups.com
Are you using Structure.toArray() at some point? the base address description "allocated@0x191418d0 (96 bytes) (shared from allocated@0x19141490 (1184 bytes) (shared from auto-allocated@0x19141490 (9472 bytes)))” indicates at least two levels of “sharing”.

0x19141490 9472 bytes
0x19141490 1184 bytes
0x191418d0 96 bytes (offset 1088 bytes from 0x19141490)

It’s important to figure out exactly *where* the address of your struct/union is incorrect. If it’s the second array element, and 8 bytes too high, then that indicates 8 bytes too much padding. If it’s the third array element, that implies 4 bytes too much padding. If you can make a test case it’d be ideal, construct a test duplicating your operation and demonstrating exactly where the offset is going contrary to what is expected.

Mark Riley

unread,
Dec 2, 2013, 12:47:53 PM12/2/13
to jna-...@googlegroups.com
Yes, I am using Structure.toArray().

public SHIPDeviceProgramInfo[] getUsbDevices() {

SHIPFlashProgrammerJNA sfpLibrary = SHIPFlashProgrammerJNA.INSTANCE;

short bufLen = SHIPFlashProgrammerJNA.SHIP_BUFFER_LENGTH;
SHIPDeviceProgramInfo base = new SHIPDeviceProgramInfo();
SHIPDeviceProgramInfo[] devProgramInfo = (SHIPDeviceProgramInfo[]) base.toArray(SHIP_PROGRAM_DEVICE_MAX);

/*
* Find valid devices
*/
sfpLibrary.SHIP_USBGetDevicePath(USBGUID, devProgramInfo, SHIP_PROGRAM_DEVICE_MAX, bufLen);
for (int i = 0; i < SHIP_PROGRAM_DEVICE_MAX; i++) {
if (devProgramInfo[i].deviceInfo.devFound) {
devProgramInfo[i].deviceInfo.devType = SHIPFlashProgrammerJNA.SHIP_DEVICE_USB;
}
}

return devProgramInfo;
}

The address results I showed you come from Structure[0] when I make a call to the DLL to return the Serial Number of the USB Device I've attached.

Timothy Wall

unread,
Dec 2, 2013, 9:18:27 PM12/2/13
to jna-...@googlegroups.com
Is it possible that your library is expecting or forcing memory alignment? You *can* force memory alignment with Memory.align(x); it might be worth trying that to see if a 16-byte alignment makes a difference (allocate memory a bit larger than you need and then align it).

I wouldn’t expect a library to write _prior_ to the address passed to it, which seems to be what you’ve indicated. You said that you’re missing the first 8 bytes.

You’re using windows; is it 32-bit or 64-bit?

Mark Riley

unread,
Dec 3, 2013, 10:24:13 AM12/3/13
to jna-...@googlegroups.com
I am using a 64Bit OS.

The Library works fine when running on a 32Bit JDK but on the 64BIT JDK the first 8 expected bytes are missing. I've tested the C Code on 64 Bit and 32Bit and get the expected results with both. Using JNA to access the DLL is where I'm seeing issues.

These are the memory dumps side by side and I shifted the 64 Bit one down to show you what I'm referencing.

Expected Returned
(Accurate (Incorrect
32 Bit 64 Bit
Return) Return)

[09000000]
[00140502]
[30323035] [30323035]
[31343030] [31343030]
[30303030] [30303030]
[30303039] [30303039]
[00000000] [00000000]
[00000000] [00000000]
[24301515] [24301515]
[020e13a8] [020e13a8]
[41383133] [41383133]
[30453032] [30453032]
[31353135] [31353135]
[33303234] [33303234]
[00000000] [00000000]
[00000000] [00000000]
[ffffffff] [ffffffff]
[ffffffff] [ffffffff]
[46464646] [46464646]
[46464646] [46464646]
[46464646] [46464646]
[46464646] [46464646]
[00000000] [00000000]
[00000000] [00000000]
[00000000]
[00000000]

Timothy Wall

unread,
Dec 3, 2013, 10:11:20 PM12/3/13
to jna-...@googlegroups.com
Given that your data is offset on the very first element, it would seem that your DLL is writing to the incorrect address.

Can you allocate a block of com.sun.jna.Memory big enough to hold your data, pass that to your DLL, and then dump the results?

Mark Riley

unread,
Dec 6, 2013, 1:41:10 PM12/6/13
to jna-...@googlegroups.com
So I think I made some progress.

I changed the SHIP_SN Structure to just a byte[] and I'm using a table of offsets to get the portions I need. This seems to give me the correct values on 64-bit now, but now 32-Bit is incorrect (Its padding the front with 4 bytes, all 0's). This is leading me to believe there is an issue in the structure that SHIP_SN was being used in, and not actually SHIP_SN its self.

I'm attempting to turn all the variables that I don't care about in the structure to byte arrays.

I'm not sure this is the right approach though. Any insight would be helpful as the parent structure is much more complex.

Mark Riley

unread,
Dec 6, 2013, 1:51:26 PM12/6/13
to jna-...@googlegroups.com
Following up my last e-mail:

One thing I've run into in the native code is it is using HANDLE in winnt.h

Could this be causing alignment issues in JNA when I use com.sun.jna.platform.win32.WinNT.HANDLE?

I'm thinking this might be my culprit. I use com.sun.jna.platform.win32.WinNT.HANDLE twice in the structure prior to SHIP_SN.

Mark Riley

unread,
Dec 11, 2013, 4:56:00 PM12/11/13
to jna-...@googlegroups.com
So I profiled my structures using the JNA toString(Debug); and there are differences in the bytes JNA allocates


SHIPDeviceInfo
32 Bit: 276 bytes
64 Bit: 288 bytes

SHIPUSBCommPort
32bit: 16 bytes
64 Bit: 24 bytes

SHIPBridgeSNFields
32 Bit: 8 bytes
64 Bit: 8 byes

SHIP_SN
32 bit: 96 bytes
64 bit: 96 bytes

The two classes that resized between 32 bit and 64 bit both used HANDLE and ShipDeviceInfo used WINUSB_INTERFACE_HANDLE. I suspect that my issue resolves around these two variables types.

The native headers for those look as such:

Native:
struct _SHIP_DevInfo {
char devicePath[256];
SHIP_Device_Type devType;
SHIP_Bool devFound;
HANDLE deviceHandle;
WINUSB_INTERFACE_HANDLE winUSBHandle;
UCHAR deviceSpeed;
UCHAR bulkInPipe;
UCHAR bulkOutPipe;
UCHAR interruptPipe;
};
typedef struct _SHIP_DevInfo SHIP_DevInfo;

Java

public class SHIPDeviceInfo extends Structure {

public byte[] devicePath = new byte[SHIPFlashProgrammerJNA.SHIP_BUFFER_LENGTH];
public byte devType;
public boolean devFound;
public HANDLE deviceHandle;
public SHIPFlashProgrammerJNA.WINUSB_INTERFACE_HANDLE winUSBHandle;
public byte deviceSpeed;
public byte bulkInPipe;
public byte bulkOutPipe;
public byte interruptPipe;

public SHIPDeviceInfo() {
super();
}

@Override
protected List getFieldOrder() {
return Arrays.asList("devicePath", "devType", "devFound", "deviceHandle", "winUSBHandle", "deviceSpeed", "bulkInPipe", "bulkOutPipe", "interruptPipe");
}

public SHIPDeviceInfo(byte[] devicePath, byte devType, boolean devFound, HANDLE deviceHandle, WINUSB_INTERFACE_HANDLE winUSBHandle, byte deviceSpeed, byte bulkInPipe, byte bulkOutPipe, byte interruptPipe) {
super();
if (this.devicePath.length != devicePath.length) {
throw new IllegalArgumentException(String.format("Device Path array must be %d in length", SHIPFlashProgrammerJNA.SHIP_BUFFER_LENGTH));
}
this.devicePath = devicePath;
this.devType = devType;
this.devFound = devFound;
this.deviceHandle = deviceHandle;
this.winUSBHandle = winUSBHandle;
this.deviceSpeed = deviceSpeed;
this.bulkInPipe = bulkInPipe;
this.bulkOutPipe = bulkOutPipe;
this.interruptPipe = interruptPipe;
}
}


Native

struct _SHIP_USBCommPort {
char devicePath[14];
SHIP_Bool devFound;
HANDLE deviceHandle;
};
typedef struct _SHIP_USBCommPort SHIP_USBCommPort;

Java

public class SHIPUSBCommPort extends Structure {

public byte[] devicePath = new byte[SHIPFlashProgrammerJNA.SHIP_COM_PORT_NAME_LENGTH];
public boolean devFound;
public HANDLE deviceHandle;

public SHIPUSBCommPort() {
super();
}

@Override
protected List getFieldOrder() {
return Arrays.asList("devicePath", "devFound", "deviceHandle");
}

public SHIPUSBCommPort(byte[] devivePath, boolean devFound, HANDLE deviceHandle) {
super();
if (this.devicePath.length != devicePath.length) {
throw new IllegalArgumentException(String.format("Device Path array must be %d in length", SHIPFlashProgrammerJNA.SHIP_COM_PORT_NAME_LENGTH));
}
this.devicePath = devivePath;
this.devFound = devFound;
this.deviceHandle = deviceHandle;
}
}


These variables are defines as such:

public class WINUSB_INTERFACE_HANDLE extends PointerType{
public WINUSB_INTERFACE_HANDLE(){
super();
}

public WINUSB_INTERFACE_HANDLE(Pointer p){
super(p);
}
}

public class HANDLE extends PointerType{
public HANDLE(){
super();
}

public HANDLE(Pointer p){
super(p);

Mark Riley

unread,
Dec 11, 2013, 5:11:53 PM12/11/13
to jna-...@googlegroups.com
Oops! I didn't see your e-mail including.

> Can you allocate a block of com.sun.jna.Memory big enough to hold your data, pass that to your DLL, and then dump the results?

I'm not sure how to achieve this using JNA. My structures data is populated directly by the DLL.

Mark Riley

unread,
Dec 11, 2013, 7:00:14 PM12/11/13
to jna-...@googlegroups.com
I finally fixed it!

There was a single structure that used an Integer in the native code that I used a Long for in the JNA code. Strange this worked for 32 bit and not 64 bit.

Let this be a lesson to me to not dive down one hole too far! The solution was much simpler than I led myself to believe.

Thanks for the help and keeping my mind engaged in the issue.
Reply all
Reply to author
Forward
0 new messages