我正在研究用 C 语言编写的 Nikon SDK 和带有 JNA 库的 Java 程序之间的包装。
所有进程都以 dll 内的 EntryPoint (MAIDEntryPoint) 结束。 这个EntryPoint在C中的签名是:
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
我感兴趣的值是
NKPARAM data
,即下一个结构:
//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;
EntryPoint 的范围是填充参数
LPVOID pData
。
pData
参数是一个以这种方式分配的指针:
NkMAIDEnum stEnum;
stEnum.pData = malloc(stEnum.ulElements * stEnum.wPhysicalBytes);
我所做的是“翻译”jna 结构和 EntryPoint,即:
//EntryPoint
int MAIDEntryPoint(NkMAIDObject pObject,
int kNkMAIDCommand_capGetArray,
int ulCapID,
int kNkMAIDDataType_enumPtr,
NkMAIDEnum nkMAIDEnum,
Object o,
int i);
Struct 将被定义为 Java 类:
@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;
}
此时我将
Pointer pData
初始化为:
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);
然后将其传递给 EntryPoint,但我收到一个 Invalid Access Memory 。 我认为问题是如何初始化Java-JNA部分中的pData或者NkMAIDEnum类中的pData应该是什么样的数据
例如,我不关心其他 EntryPoint 的参数,因为它们是正确的,并且参数
nkMAIDEnum.ulElements
和 nkMAIDEnum.wPhysicalBytes
都是不等于 0 或 null 的数字。
请帮助我理解我错在哪里,我被困住了
我看到三个可能的问题:
JNA 需要足够的类型信息才能在结构(用于内存分配)或方法/函数签名(用于堆栈)中分配正确的字节数。
您使用
Object
来映射 MAIDEntryPoint()
中的第六个参数肯定是错误的。 JNA 无法知道需要多少字节。由于该参数实际上是 LPNKFUNC pfnComplete
,因此看起来 Pointer
是它的正确映射。
另一种可能性是,如果您错误地映射(或分配)了作为
NkMAIDObject
第一个参数的 MAIDEntryPoint()
类型。您还没有向我们展示映射,但这很可能是一个不正确的分配。
最后,您指示本机分配已通过
malloc(stEnum.ulElements * stEnum.wPhysicalBytes)
和状态 完成
参数
和nkMAIDEnum.ulElements
是不等于0或空的数字。nkMAIDEnum.wPhysicalBytes
new NkMAIDEnum()
定义一个新结构,并且不为 .ulElements
或 .wPhysicalBytes
分配任何值,因此它们实际上被初始化为零。 (除非您有代码,否则您不会向我们展示。)