I'm working on a wrap between a Nikon SDK written in C and a Java program with JNA libruary.
All the process ended in a EntryPoint (MAIDEntryPoint) that is inside a dll. The signature of this EntryPoint in C is:
SLONG CallMAIDEntryPoint(
LPNkMAIDObject pObject, // module, source, item, or data object
ULONG ulCommand, // Command, one of eNkMAIDCommand
ULONG ulParam, // parameter for the command
ULONG ulDataType, // Data type, one of eNkMAIDDataType
NKPARAM data, // Pointer or long integer
LPNKFUNC pfnComplete, // Completion function, may be NULL
NKREF refComplete ) // Value passed to pfnComplete
The LPNkMAIDObject pObject is a struct defined in C as:
typedef struct tagNkMAIDObject
{
ULONG ulType; // One of eNkMAIDObjectType
ULONG ulID;
NKREF refClient;
NKREF refModule;
} NkMAIDObject, FAR* LPNkMAIDObject;
the value I'm interesting on is the NKPARAM data that is this next struct:
//stEnum Struct
typedef struct tagNkMAIDEnum
{
ULONG ulType; // one of eNkMAIDArrayType
ULONG ulElements; // total number of elements
ULONG ulValue; // current index
ULONG ulDefault; // default index
SWORD wPhysicalBytes; // bytes per element
LPVOID pData; // allocated by the client
} NkMAIDEnum, FAR* LPNkMAIDEnum;
and the scope of the EntryPoint is to populate the argument LPVOID pData.
The pData argument is a pointer that is allocate in this way:
NkMAIDEnum stEnum;
stEnum.pData = malloc(stEnum.ulElements * stEnum.wPhysicalBytes);
what I done is to "translate" whit jna the struct and the EntryPoint, that are this:
//EntryPoint
int MAIDEntryPoint(NkMAIDObject pObject,
int kNkMAIDCommand_capGetArray,
int ulCapID,
int kNkMAIDDataType_enumPtr,
NkMAIDEnum nkMAIDEnum,
Object o,
int i);
And the Struct will be defined as a Java Class:
@Structure.FieldOrder({"ulType","ulID","refClient","refModule"})
public class NkMAIDObject extends Structure {
public NativeLong ulType; // One of eNkMAIDObjectType
public NativeLong ulID;
public TagRefObj.ByReference refClient;
//public Pointer refClient;
public Pointer refModule;
}
@Structure.FieldOrder({"ulType", "ulElements", "ulValue", "ulDefault", "wPhysicalBytes", "pData"})
public class NkMAIDEnum extends Structure {
public NativeLong ulType;
public NativeLong ulElements;
public NativeLong ulValue;
public NativeLong ulDefault;
public short wPhysicalBytes;
public Pointer pData;
}
At this point I initializa the Pointer pData as:
NkMAIDEnum nkMAIDEnum = new NkMAIDEnum ();
nkMAIDEnum.pData = new Memory(nkMAIDEnum.ulElements.longValue()*nkMAIDEnum.wPhysicalBytes);
nResult = INSTANCE.MAIDEntryPoint(
pRefMod.pObject,
kNkMAIDCommand_CapGetArray,
ulCapID,
kNkMAIDDataType_EnumPtr,
nkMAIDEnum,
null,
0);
And then pass it to the EntryPoint, but I receive an Invalid Access Memory . I think the problem is how to initialize the pData in the Java-JNA part or also what kind of data should be the pData in the class NkMAIDEnum
For instance, I don't care about the other EntryPoint's parameter because they're right, and alto the parameters nkMAIDEnum.ulElements and nkMAIDEnum.wPhysicalBytes are number not equals to 0 or null, they are respectively nkMAIDEnum.ulElements = 1 and nkMAIDEnum.wPhysicalBytes = 4 they are initialize in a previously EntryPoint, that is exactly the same as the one written here but instade of initialize the pData, it initialize the nkMAIDEnum.ulElements and nkMAIDEnum.wPhysicalBytes.
Please help me to understan where I'm wrong, I'm stuck
I see three possible problems:
JNA needs enough type information to be able to allocate the correct number of bytes in structures (for memory allocation) or method/function signatures (for the stack).
Your use of
Objectto map the 6th argument inMAIDEntryPoint()is most certainly wrong. JNA has no way to know how many bytes that takes. Since that argument is actuallyLPNKFUNC pfnCompleteit looks like aPointerwould be the correct mapping for it.Another possibility is if you've incorrectly mapped (or allocated) the
NkMAIDObjecttype that is the first argument toMAIDEntryPoint(). You haven't shown us the mapping, but it could very well be an incorrect allocation.Finally you indicate the native allocation is done with
malloc(stEnum.ulElements * stEnum.wPhysicalBytes)and statenew NkMAIDEnum()and do not assign any values to.ulElementsor.wPhysicalBytesso they are, in fact, initialized to zero. (Unless you have code you aren't showing us.)