まず、私は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
を調べて、真の呼び出し規約が何であるかを判断する必要があります。
どのようにwave_dataの長さを知っていますか? wave_dataとwave_lengthを逆にするように、実際のデータの前に長さを置く必要があります。 – jdweng
データの長さは固定されています。たとえば、100としましょう。 – Yao
@jdweng構造体の長さフィールドがデータフィールドの前に来るのはなぜですか。それは構造体のレイアウトを決定するだけです。プログラムは、それが好きな順序でフィールドにアクセスできます。 –