우선 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();
}
여기 내 가정이 첫 번째 매개 변수가 입력에 사용된다는 점이다, 출력을위한 두 번째 매개 변수. 하지만 출력 구조체에 웨이브 데이터 배열을 할당해야한다는 책임이 호출자에게 있습니다.
나는 또한 호출 규칙을 사용하고 있지만 C++ 매크로 STRUCTDLL_API
을 검사하여 실제 호출 규칙이 무엇인지 판별해야합니다.
wave_data의 길이를 어떻게 알 수 있습니까? wave_data와 wave_length가 반전되어야하므로 길이는 실제 데이터보다 커야합니다. – jdweng
데이터의 길이는 고정되어 있습니다 (예 : 100). – Yao
@jdweng 구조체의 길이 필드가 데이터 필드 앞에 오는 이유는 무엇입니까? 그것은 단지 구조체의 레이아웃을 결정합니다. 프로그램은 원하는 순서대로 필드에 액세스 할 수 있습니다. –