0

ベンダー提供の .DLL と、無線ハードウェアとのやり取りに使用するオンライン API があります。JNA を使用して、Java を介してエクスポートされた関数にアクセスしています (C/C++ を知らないため)。基本的なメソッドを呼び出し、いくつかの API 構造を正常に使用できますが、コールバック構造に問題があります。私は TutorTutor ガイドhereに従い、Mr. Wall の信頼できるガイドhereも試しましたが、構造体に設定されたコールバックの Java 側の構文を正しく定式化できませんでした。

このエクスポートされた関数を使用する必要があります:

BOOL __stdcall SetCallbacks(INT32 hDevice,
                            CONST G39DDC_CALLBACKS *Callbacks, DWORD_PTR UserData);

この関数は、C/C++ 構造体を参照します。

typedef struct{
    G39DDC_IF_CALLBACK               IFCallback;
    //more omitted
} G39DDC_CALLBACKS;

...APIによると、これらのメンバーがあります(これはエクスポートされた関数ではないことに注意してください):

VOID __stdcall IFCallback(CONST SHORT *Buffer, UINT32 NumberOfSamples,
                          UINT32 CenterFrequency, WORD Amplitude,
                          UINT32 ADCSampleRate, DWORD_PTR UserData);
//more omitted

私は G39DDCAPI.java を持っており、ここで DLL ライブラリをロードし、JNA の助けを借りて Java で API エクスポート関数を再現しました。それへの単純な呼び出しはうまく機能します。

上記の 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);

編集番号2:

1 つのコールバックがある程度機能していますが、バッファを制御できません。さらに苛立たしいことに、メソッドを呼び出す 1 回の呼び出しでカスタム コールバックが複数回実行され、通常は複数の出力ファイルが作成されます (結果は実行ごとに大幅に異なります)。Java側でメモリを正しく割り当てていないためか、C / C ++側でメモリを解放できないためか、Javaにバッファにアクセスするように指示する手がかりがないためかどうかはわかりません。関連するコードは次のようになります。

//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("/users/user/G39DDC_Scans/");
            if (!filePath.exists()){
                System.out.println("Making new directory...");
                filePath.mkdir();
            }

            String filename="Scan_"+System.currentTimeMillis();
            File fille= new File("/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
4

1 に答える 1