2017-12-21 12 views
0

DLL C++では、構造体は次のように定義されています。パス構造体* ++のdll

struct WAVE_INFO { 
    int channel_num; 
    int audio_type; 
    char *wave_data; 
    int wave_length; 
}; 

そして、このような呼び出し方法:私のC#の構造体の

extern "C" STRUCTDLL_API int processStruct(WAVE_INFO *pIn, WAVE_INFO *pOut); 

wave_data char []または文字列ではなく、バイト配列(byte [])****でなければなりません。どのように私は構造体とメソッドを定義する必要がありますC#でどこにDLLが呼び出されますか?そして、wave_dateの長さは固定されています。たとえば、100のようにしましょう。

+1

どのようにwave_dataの長さを知っていますか? wave_dataとwave_lengthを逆にするように、実際のデータの前に長さを置く必要があります。 – jdweng

+0

データの長さは固定されています。たとえば、100としましょう。 – Yao

+0

@jdweng構造体の長さフィールドがデータフィールドの前に来るのはなぜですか。それは構造体のレイアウトを決定するだけです。プログラムは、それが好きな順序でフィールドにアクセスできます。 –

答えて

1

まず、私はC++構造体が正しく宣言されていないと言います。ペイロードはバイナリデータなので、配列はchar*ではなくunsigned char*でなければなりません。

これをそのまま残しておくと、構造体は配列のためにマーシャリングに少し混乱します。それはこのような何かを行く:私たちは整列化される構造体でbyte[]を使用することはできません

[StructLayout(LayoutKind.Sequential)] 
struct WAVE_INFO 
{ 
    public int channel_num; 
    public int audio_type; 
    public IntPtr wave_data; 
    public int wave_length; 
} 

。代わりに、配列をIntPtrと宣言して、自分自身を整理する必要があります。最もきれいな方法は、byte[]配列を宣言し、GCHandleでそれらを固定することです。

インポート機能は次のようになります。

[DllImport(dllfilename, CallingConvention = CallingConvention.Cdecl)] 
static extern int processStruct(ref WAVE_INFO infoIn, ref WAVE_INFO infoOut); 

と機能にかなり厄介な呼び出しはこのように書き:ここ

var dataIn = new byte[256]; 
// populate the input data array 
var dataOut = new byte[256]; 

GCHandle dataInHandle = GCHandle.Alloc(dataIn, GCHandleType.Pinned); 
try 
{ 
    GCHandle dataOutHandle = GCHandle.Alloc(dataOut, GCHandleType.Pinned); 
    try 
    { 
     WAVE_INFO infoIn; 
     infoIn.audio_type = 1; 
     infoIn.channel_num = 2; 
     infoIn.wave_data = dataInHandle.AddrOfPinnedObject(); 
     infoIn.wave_length = dataIn.Length; 

     WAVE_INFO infoOut = new WAVE_INFO(); 
     infoOut.wave_data = dataOutHandle.AddrOfPinnedObject(); 
     infoOut.wave_length = dataOut.Length; 

     int retval = processStruct(ref infoIn, ref infoOut); 
     // dataOut should have been populated by processStruct 
    } 
    finally 
    { 
     dataOutHandle.Free(); 
    } 
} 
finally 
{ 
    dataInHandle.Free(); 
} 

私の仮定は、最初のパラメータを入力するために使用されていることです、出力のための第2パラメータ。しかし、出力構造体にwaveデータ配列を割り当てるという責任が呼び出し側にあります。

私も呼び出し規約を想定していましたが、C++マクロSTRUCTDLL_APIを調べて、真の呼び出し規約が何であるかを判断する必要があります。

+0

ありがとう、David。私はちょうどあなたのコードをテストし、それは完全に正常に動作します!助けてください。 – Yao