提问人:Silvia Francia 提问时间:11/14/2023 最后编辑:Silvia Francia 更新时间:11/14/2023 访问量:44
SDK Nikon C与JNA
SDK Nikon C with JNA
问:
我正在用 C 编写的尼康 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
是 C 中定义的结构体,如下所示:LPNkMAIDObject pObject
typedef struct tagNkMAIDObject
{
ULONG ulType; // One of eNkMAIDObjectType
ULONG ulID;
NKREF refClient;
NKREF refModule;
} NkMAIDObject, FAR* LPNkMAIDObject;
我感兴趣的值是下一个结构: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);
我所做的是“翻译”whit 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","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;
}
在这一点上,我将初始化为: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,但我收到一个无效的访问存储器。 我认为问题是如何初始化 Java-JNA 部分中的 pData,或者 NkMAIDEnum 类中的 pData 应该是什么类型的数据
例如,我不关心另一个 EntryPoint 的参数,因为它们是正确的,并且参数和 是数字不等于 0 或 null,它们分别是,它们在以前的 EntryPoint 中初始化,这与这里写的完全相同,但初始化 ,它初始化 和 .nkMAIDEnum.ulElements
nkMAIDEnum.wPhysicalBytes
nkMAIDEnum.ulElements = 1
nkMAIDEnum.wPhysicalBytes = 4
pData
nkMAIDEnum.ulElements
nkMAIDEnum.wPhysicalBytes
请帮助我了解我错了,我被困住了
答:
我看到三个可能的问题:
JNA 需要足够的类型信息才能在结构(用于内存分配)或方法/函数签名(用于堆栈)中分配正确数量的字节。
你用 来映射第 6 个参数肯定是错误的。JNA 无法知道这需要多少字节。由于该参数实际上是,因此看起来 a 将是它的正确映射。
Object
MAIDEntryPoint()
LPNKFUNC pfnComplete
Pointer
另一种可能性是,如果错误地映射(或分配)了作为第一个参数的类型。您没有向我们展示映射,但这很可能是不正确的分配。
NkMAIDObject
MAIDEntryPoint()
最后,您指示本机分配已完成,并带有 state
malloc(stEnum.ulElements * stEnum.wPhysicalBytes)
参数 和 ARE 数字不等于 0 或 null。
nkMAIDEnum.ulElements
nkMAIDEnum.wPhysicalBytes
- 但是,您不会显示这些内容的分配位置。您只需定义一个新结构,并且不为其分配任何值,或者实际上它们被初始化为零。(除非你有代码,否则你不会向我们显示。
new NkMAIDEnum()
.ulElements
.wPhysicalBytes
评论