2013-06-27 2 views
0

JNA를 처음 사용하는 경우입니다. 내가 뭘 하려는지 (C 코드) -> (서명되지 않은 긴 DeviceTypes, NeoDevice * pNeoDevice, int * pNumDevices) ... (JNA 양식) -> (int, NeoDevice.getPointer(), int [] myInt) 을 매개 변수로 사용합니다. 이 함수는 구조체의 필드에 쓰고 업데이트 된 필드를보고 싶습니다.JNA updateStructureByReference() trouble

여기 내 JNA 구조체이다 'NeoDevice'나는 필드를 업데이트하는 'updateStrucureByReference (클래스 타입, 객체, 객체의 포인터를)'를 사용하려고 시도하고

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 { 

    }; 
} 

. 내 '클래스 형식'매개 변수가 맞는지 또는 그럴 것이라고 생각하지 않습니까? 내가 다른 일을하고 있니? 모든 입력은 크게 감사하겠습니다.

나는 모두 0으로 표시되는 필드를 println하려고하면 여전히. 내 메인 클래스에서

은 내가

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

답변

0

Structure.updateStructureByReference 당신이 뭔가를 잘못하고있는 첫 번째 표시해야 공용 함수가 아닌 사실이있다.

구조체 필드를 volatile으로 선언하면 JNA에 네이티브 함수 호출 전에 자동으로 수행되는 네이티브 메모리에 값이 복사되는 것을 피하게됩니다. 자바 필드의 값을 네이티브 함수에 전달하려는 경우에만 문제가됩니다. 결과를 다시 읽는 데에만 관심이 있다면 volatile은 중요하지 않습니다.

icsneoFindNeoDevicesNeoDevice 인스턴스를 포인터가 아닌 두 번째 인수로 사용하도록 선언 된 경우 JNA는 자동으로 구조 필드를 올바르게 동기화합니다 (함수 호출 후 Java 필드를 업데이트 함). JNA가 Structure 인수를 만나면 호출 전에 모든 Java 필드를 원시 메모리에 기록하고 나중에 원시 메모리를 기반으로 Java 필드를 업데이트합니다.

EDIT

the header file에 따르면 DeviceTypeNativeLong을 사용한다; 당신의 선언은 윈도우가 아닌 64 비트 시스템에서 제대로 실행되지 않을 것입니다.

라이브러리가 stdcall 호출 규칙을 사용하고 있는지 확인하십시오. 이는 공칭으로 StdCallLibrary 인터페이스를 구현하는 것을 의미합니다.

DeviceType에 대해 잘못된 ("65535") 값을 제공하고있는 것으로 보입니다. NumDevices[0]에 반환 된 값이 0이 아닌지 확인하십시오.

또한 반환 값을 확인해야합니다. 그것이 0이라면, 당신은 당신의 구조에 쓰여질 어떤 것도 기대해서는 안됩니다.

+0

입력 해 주셔서 감사합니다! 나는 단지 가치들을 다시 읽는 것에 관심이있다. Struct.updateStructureByReference가 없으면 함수를 호출하고 필드 값을 살펴보고 모두 0입니다. 필드를 볼 때도 여전히 문제가있는 경우 structure.read() 및 structure.readField()를 사용하고 있습니다. –

+0

매개 변수를 변경하기 위해 소스 코드에 액세스하지 않아 NeoDevice를 전달해야합니다. 포인터로 –

+0

'volatile '을 삭제하고 함수 호출 후에'Structure.read()'를 호출하십시오. – technomage