라디오 하드웨어와 상호 작용하는 데 사용하는 .DLL 및 온라인 API가 있습니다. JNA를 사용하여 Java를 통해 내 보낸 함수에 액세스합니다 (C/C++를 알지 못하기 때문에). 기본 메서드를 호출하고 일부 API 구조를 성공적으로 사용할 수 있지만 콜백 구조에 문제가 있습니다. 나는 TutorTutor 가이드 here을 따라 갔고 Mr. Wall의 권위있는 가이드 here도 시도했지만 구조체에 올바르게 설정된 콜백에 대한 자바 사이드 구문을 공식화하지 못했습니다.JNA를 사용하여 DLL의 내 보낸 함수를 통해 콜백의 C/C++ 구조에 액세스
이BOOL __stdcall SetCallbacks(INT32 hDevice,
CONST G39DDC_CALLBACKS *Callbacks, DWORD_PTR UserData);
이 기능은 C/C++ 구조 참조 :
나는이 보낸 된 함수 사용해야하는 API에 따라
typedef struct{
G39DDC_IF_CALLBACK IFCallback;
//more omitted
} G39DDC_CALLBACKS;
을 ...이 회원을 가지고 (이것은 내 보낸 함수가 아닙니다.) :
VOID __stdcall IFCallback(CONST SHORT *Buffer, UINT32 NumberOfSamples,
UINT32 CenterFrequency, WORD Amplitude,
UINT32 ADCSampleRate, DWORD_PTR UserData);
//more omitted
나는 G39DDCAPI.java를 가지고 있는데, DLL 라이브러리를로드하고 JNA의 도움을 받아 Java에서 함수를 내 보냈다. 그 일에 대한 간단한 호출은 잘 작동합니다.
위의 C/C++ 구조체를 다른 API 구조체의 형식으로 구현 한 G39DDC_CALLBACKS.java도 있습니다. 이 콜백 구조는 내가 구문 확실치 곳이다 :
import java.util.Arrays;
import java.util.List;
import java.nio.ShortBuffer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
public class G39DDC_CALLBACKS extends Structure {
public G39DDC_IF_CALLBACK IFCallback;
//more omitted
protected List getFieldOrder() {
return Arrays.asList(new String[] {
"IFCallback","DDC1StreamCallback" //more omitted
});
}
public static interface G39DDC_IF_CALLBACK extends StdCallCallback{
public void invoke(ShortBuffer _Buffer,int NumberOfSamples,
int CenterFrequency, short Amplitude,
int ADCSampleRate, DWORD_PTR UserData);
}
}
편집
: 내가 Technomage 제안으로 내 인수가 더 타입 안전했다. 콜백을 호출하는 여러 시도와 함께 널 포인터 예외가 계속 발생합니다. 위의 콜백 구조에 관한 구문에 대해서는 잘 모르므로 아래에서 주 문제를 정확하게 지적 할 수 없습니다. 현재 관련 부분은 다음과 같습니다int NumberOfSamples=65536;//This is usually 65536.
ShortBuffer _Buffer = ShortBuffer.allocate(NumberOfSamples);
int CenterFrequency=10000000;//Specifies center frequency (in Hz) of the useful band
//in received 50 MHz wide snapshot.
short Amplitude=0;//The possible value is 0 to 32767.
int ADCSampleRate=100;//Specifies sample rate of the ADC in Hz.
DWORD_PTR UserData = null;
G39DDC_CALLBACKS callbackStruct= new G39DDC_CALLBACKS();
lib.SetCallbacks(hDevice,callbackStruct,UserData);
//hDevice is a handle for the hardware device used-- works in other uses
//lib is a reference to the library in G39DDCAPI.java-- works in other uses
//The UserData is a big unknown-- I don't know what to do with this variable
//as a DWORD_PTR
callbackStruct.IFCallback.invoke(_Buffer, NumberOfSamples, CenterFrequency,
Amplitude, ADCSampleRate, UserData);
편집 NO 2 :
나는 하나의 콜백 다소 작업이,하지만 난 버퍼를 제어 할 필요가 없습니다. 좀 더 실망스럽게도,이 메소드를 호출하는 단일 호출은 일반적으로 여러 개의 출력 파일 (결과가 크게 달라짐)에서 사용자 정의 콜백을 여러 번 실행합니다. C/C++ 측에서 메모리를 확보 할 수 없기 때문에 또는 Java에 버퍼에 액세스하는 데 필요한 큐가 없기 때문에 Java 측에서 올바르게 메모리를 할당하지 않기 때문에 그 것인지 여부를 알 수 없습니다. 당신은 하나, StdCallCallback
을 확장 할 필요가
//before this, main method sets library, starts DDCs, initializes some variables...
//API call to start IF
System.out.print("Starting IF... "+lib.StartIF(hDevice, Period)+"\n")
G39DDC_CALLBACKS callbackStructure = new G39DDC_CALLBACKS();
callbackStructure.IFCallback = new G39DDC_IF_CALLBACK(){
@Override
public void invoke(Pointer _Buffer, int NumberOfSamples, int CenterFrequency,
short Amplitude, int ADCSampleRate, DWORD_PTR UserData ) {
//notification
System.out.println("Invoked IFCallback!!");
try {
//ready file and writers
File filePath = new File("https://stackoverflow.com/users/user/G39DDC_Scans/");
if (!filePath.exists()){
System.out.println("Making new directory...");
filePath.mkdir();
}
String filename="Scan_"+System.currentTimeMillis();
File fille= new File("https://stackoverflow.com/users/user/G39DDC_Scans/"+filename+".txt");
if (!fille.exists()) {
System.out.println("Making new file...");
fille.createNewFile();
}
FileWriter fw = new FileWriter(fille.getAbsoluteFile());
//callback body
short[] deBuff=new short[NumberOfSamples];
int offset=0;
int arraySize=NumberOfSamples;
deBuff=_Buffer.getShortArray(offset,arraySize);
for (int i=0; i<NumberOfSamples; i++){
String str=deBuff[i]+",";
fw.write(str);
}
fw.close();
} catch (IOException e1) {
System.out.println("IOException: "+e1);
}
}
};
lib.SetCallbacks(hDevice, callbackStructure,UserData);
System.out.println("Main, before callback invocation");
callbackStructure.IFCallback.invoke(s_Pointer, NumberOfSamples, CenterFrequency, Amplitude, ADCSampleRate, UserData);
System.out.println("Main, after callback invocation");
//suddenly having trouble stopping DDCs or powering off device; assume it has to do with dll using the functions above
//System.out.println("StopIF: " + lib.StopIF(hDevice));//API function returns boolean value
//System.out.println("StopDDC2: " + lib.StopDDC2(hDevice, Channel));
//System.out.println("StopDDC1: " + lib.StopDDC1(hDevice, Channel));
//System.out.println("test_finishDevice: " + test_finishDevice(hDevice, lib));
System.out.println("Program Exit");
//END MAIN METHOD
을; StdCallCallback은 백그라운드 Windows OS와의 상호 작용에만 사용되었습니다. 나는 제안이 결국 나의 질문에 답할 것이라고 생각하지만 새로운 코드를 시도하기 전에 NIO 버퍼를 읽어야한다. 지금 당장 고마워. 그리고 내가 일하는 것을 얻 자마자 나는 그 대답을 받아 들일 것인가로 점검 할 것이다. –
위에서 본 것처럼 여러 가지 유형을 변경했습니다. 내 접근 방식이 완전히 잘못되었다는 것을 알고 있습니다. 콜백 구조는 사용자 정의 콜백에 대한 액세스를 제공 할 예정입니다. 즉, 라인을 따라 어딘가에 Java 측에서 메소드 본문을 제공 할 장소가 필요합니다. 제 문제 중 일부는 컴파일러가 불평하지 않고이 작업을 수행 할 수 있습니다. –
귀하의 의견을 사용하여, 나는 자바 문법이 작동하는 문법을 가지고 있다는 것을 나타내는 일반적인 println 문을 실행할 수있게되었다. 나는 여전히 버퍼 관리에 몇 가지 문제를 겪고있다. 나중에 업데이트 할 수있게되면 나중에 업데이트를 게시 할 것입니다. –