this is the first time I am using JNA. What I am trying to do is call a function in a DLL that takes (C code)->(unsigned long DeviceTypes, NeoDevice *pNeoDevice, int *pNumDevices)...(JNA form)-> (int, NeoDevice.getPointer(), int[] myInt) as params. The function should write to the fields of the struct and I want to view the updated fields.
here is my JNA struct 'NeoDevice'
import java.util.Arrays;
import java.util.List;
import com.sun.jna.*;
public class NeoDevice extends Structure {
public volatile int DeviceType;
public volatile int Handle;
public volatile int NumberOfClients;
public volatile int SerialNumber;
public volatile int MaxAllowedClients;
public NeoDevice() {
super();
}
protected List<? > getFieldOrder() {
return Arrays.asList("DeviceType", "Handle", "NumberOfClients", "SerialNumber", "MaxAllowedClients");
}
public NeoDevice(int DeviceType, int Handle, int NumberOfClients, int SerialNumber, int MaxAllowedClients) {
super();
this.DeviceType = DeviceType;
this.Handle = Handle;
this.NumberOfClients = NumberOfClients;
this.SerialNumber = SerialNumber;
this.MaxAllowedClients = MaxAllowedClients;
}
protected ByReference newByReference() { return new ByReference(); }
protected ByValue newByValue() { return new ByValue(); }
protected NeoDevice newInstance() { return new NeoDevice(); }
public static class ByReference extends NeoDevice implements Structure.ByReference {
};
public static class ByValue extends NeoDevice implements Structure.ByValue {
};
}
I am attempting to use 'updateStrucureByReference(class type, object, pointer to object)' to update the fields. I dont believe my 'class type' param is correct or is it? am i doing something else wronge? any input would be greatly appreciated.
when i try to println the fields they appear to all be zero still.
In my main class i have
NeoDevice.ByReference myDeviceByRef = new NeoDevice.ByReference();
NeoDevice.ByValue myDeviceByVal = new NeoDevice.ByValue();
NeoDevice myDevice = new NeoDevice();
int [] NumDevices;
NumDevices = new int [1];
NumDevices[0] = 1;
int iResult = n40.icsneoFindNeoDevices(65535, myDeviceByRef.getPointer(), NumDevices);
int icsneoGetDLLVersion = n40.icsneoGetDLLVersion();
Object serialN = myDeviceByRef.readField("SerialNumber");
NeoDevice.ByReference myDeviceBy = Structure.updateStructureByReference(NeoDevice.ByReference, myDeviceByRef, myDeviceByRef.getPointer());
The fact that
Structure.updateStructureByReference
is not a public function should be your first indication that you're doing something wrong.By declaring your structure fields
volatile
, you are telling JNA to avoid copying their values to native memory, which it ordinarily does automatically prior to a native function call. This is only a problem if you intend for values in the Java fields to be passed to the native function; if you're only interested in reading back the results,volatile
doesn't matter.If your
icsneoFindNeoDevices
were declared to take aNeoDevice
instance as its second argument (rather than a pointer), then JNA would automatically synch the structure fields properly (it will update the Java fields after the function call). When JNA encounters aStructure
argument, it writes all Java fields to native memory before the call and updates them based on native memory afterwards.EDIT
According to the header file,
DeviceType
should useNativeLong
; your declaration will fail to run properly on any 64-bit system other than windows.Make sure your library is using the
stdcall
calling convention (nominally that means implement theStdCallLibrary
interface).It also seems that you're providing an invalid ("65535") value for the DeviceType; check that the value returned in
NumDevices[0]
is not zero.You should also check the return value; if it's zero, then you shouldn't expect anything to be written to your structure.