SDK Nikon C与JNA

SDK Nikon C with JNA

提问人:Silvia Francia 提问时间:11/14/2023 最后编辑:Silvia Francia 更新时间:11/14/2023 访问量:44

问:

我正在用 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 pDatapData

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.ulElementsnkMAIDEnum.wPhysicalBytesnkMAIDEnum.ulElements = 1nkMAIDEnum.wPhysicalBytes = 4pDatankMAIDEnum.ulElementsnkMAIDEnum.wPhysicalBytes

请帮助我了解我错了,我被困住了

Java C 开发工具包 java-native-interface jna

评论


答:

1赞 Daniel Widdis 11/14/2023 #1

我看到三个可能的问题:

  1. JNA 需要足够的类型信息才能在结构(用于内存分配)或方法/函数签名(用于堆栈)中分配正确数量的字节。

    你用 来映射第 6 个参数肯定是错误的。JNA 无法知道这需要多少字节。由于该参数实际上是,因此看起来 a 将是它的正确映射。ObjectMAIDEntryPoint()LPNKFUNC pfnCompletePointer

  2. 另一种可能性是,如果错误地映射(或分配)了作为第一个参数的类型。您没有向我们展示映射,但这很可能是不正确的分配。NkMAIDObjectMAIDEntryPoint()

  3. 最后,您指示本机分配已完成,并带有 state malloc(stEnum.ulElements * stEnum.wPhysicalBytes)

参数 和 ARE 数字不等于 0 或 null。nkMAIDEnum.ulElementsnkMAIDEnum.wPhysicalBytes

  • 但是,您不会显示这些内容的分配位置。您只需定义一个新结构,并且不为其分配任何值,或者实际上它们被初始化为零。(除非你有代码,否则你不会向我们显示。new NkMAIDEnum().ulElements.wPhysicalBytes

评论

0赞 Silvia Francia 11/14/2023
你好!我添加了一个规范,如果你需要更多,我会尝试添加它,但非常困难,因为有很多代码XD。对你来说,第 1 点。我将尝试指定pfnComplete的类型,但是一个空值,所以我不知道它是否重要
0赞 Daniel Widdis 11/15/2023
@SilviaFrancia 这可能是一个指针,但 JNA/Native 需要知道它是 8 个字节的 0。