【问题标题】:JNA updateStructureByReference() troubleJNA updateStructureByReference() 麻烦
【发布时间】:2013-06-25 07:14:57
【问题描述】:

这是我第一次使用 JNA。我想要做的是调用一个DLL中的函数,它需要(C代码)->(unsigned long DeviceTypes,NeoDevice *pNeoDevice,int *pNumDevices)...(JNA形式)-> (int, NeoDevice.getPointer(), int[] myInt) 作为参数。该函数应该写入结构的字段,我想查看更新的字段。

这是我的 JNA 结构“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 {

    };
}

我正在尝试使用“updateStructureByReference(类类型、对象、指向对象的指针)”来更新字段。我不相信我的“类类型”参数是否正确?我做错了什么吗?任何意见将不胜感激。

当我尝试打印字段时,它们似乎仍然为零。

在我的主要课程中,我有

    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());

【问题讨论】:

    标签: java dll jna


    【解决方案1】:

    Structure.updateStructureByReference 不是公共函数这一事实应该是您做错事的第一个迹象。

    通过声明结构字段volatile,您是在告诉 JNA 避免将它们的值复制到本机内存,这通常会在本机函数调用之前自动执行。如果您打算将 Java 字段中的值传递给本机函数,这只是一个问题;如果您只对回读结果感兴趣,volatile 没关系。

    如果您的 icsneoFindNeoDevices 被声明为将 NeoDevice 实例作为其第二个参数(而不是指针),那么 JNA 将自动正确同步结构字段(它将在函数调用后更新 Java 字段)。当 JNA 遇到 Structure 参数时,它会在调用之前将所有 Java 字段写入本机内存,然后根据本机内存更新它们。

    编辑

    根据the header fileDeviceType应该使用NativeLong;您的声明将无法在 Windows 以外的任何 64 位系统上正常运行。

    确保您的库使用stdcall 调用约定(名义上这意味着实现StdCallLibrary 接口)。

    您似乎还为 DeviceType 提供了无效 ("65535") 值;检查NumDevices[0] 中返回的值是否不为零。

    您还应该检查返回值;如果它是零,那么你不应该期望任何东西被写入你的结构。

    【讨论】:

    • 感谢您的意见!我只对读回这些值感兴趣。如果没有 Structure.updateStructureByReference,在我调用函数并尝试查看字段值之后,它们都为零。我目前正在使用 structure.read() 和 structure.readField() 来查看字段,但仍然遇到问题
    • 我也无权访问源代码来更改参数,所以我不得不将 NeoDevice 作为指针传递
    • 只需删除volatile 并在函数调用后调用Structure.read()
    • 感谢您的帮助technomage,但仍然没有成功。
    • 我唯一能看到的错误是在我的班级中定义了我的结构。我会仔细研究一下。
    猜你喜欢
    • 2010-11-11
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多