2017-12-21 9 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 []) ****이어야합니다. dll이 호출되는 C#에서 구조체와 메서드를 어떻게 정의해야합니까? 그리고 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(); 
} 

여기 내 가정이 첫 번째 매개 변수가 입력에 사용된다는 점이다, 출력을위한 두 번째 매개 변수. 하지만 출력 구조체에 웨이브 데이터 배열을 할당해야한다는 책임이 호출자에게 있습니다.

나는 또한 호출 규칙을 사용하고 있지만 C++ 매크로 STRUCTDLL_API을 검사하여 실제 호출 규칙이 무엇인지 판별해야합니다.

+0

고마워, 데이빗. 방금 코드를 테스트했는데 완벽하게 작동합니다! 도와주세요. – Yao