2009-08-03 5 views
3

은 내가 C의 ++ 구조체의 PInvoke 오류

struct UnmanagedStruct 
{ 
    char* s; 
    // Other members 
};

및 C++ 라이브러리

extern "C" UnmanagedStruct __declspec(dllexport) foo(char* input); 

를 노출

struct ManagedStruct { 
    [MarshalAs(UnmanagedType.LPStr)] 
    string s; 
    // Other members 
}

C#을 구조체를 그리고있다 수입품 :

[DllImport("SomeDLL.dll", CharSet = CharSet.Ansi)] 
    static extern ManagedStruct foo(string input); 
나는이 함수를 호출 할 때 16,

그러나 나는

MarshalDirectiveException은 처리되지 않은

방법의 유형 서명이 호환 PInvoke를하지 않는했다 얻는다.

구조체에서 char * 및 s를 제거하면이 함수 호출이 작동합니다.

답변

4

이 시나리오에서는 문자열을 직접 사용하지 마십시오. 대신 형식을 IntPtr 값으로 전환하고 적절하게 Marshal.PtrToStringAuto/Ansi/Uni를 사용하십시오. 이 경우 네이티브 코드가 char*이므로 PtrToStringAnsi가 최선의 선택입니다.

struct ManagedStruct { 
    IntPtr s; 
    public string sAsString { get { return Marshal.PtrToStringAnsi(s); } } 
} 
+0

왜 그렇게해야합니까? 나는이 질문을 더 일찍 요청했고 사람들은 모두 그것이 "효과가있다"고 모두 말했습니다. – DevDevDev

+0

@SteveM, 문자열 + PInvoke = 어렵습니다. 문자열은 여러 시나리오에서 작동하지만 많은 다른 것들은 실패합니다. :) 구조체의 필드로서의 문자열은 메모리 관리에 큰 문제가 있기 때문에 특히 어렵습니다. 특히 CLR은 관리되는 문자열을 만드는 데 사용되는 메모리로 무엇을해야합니까? 그것을 해방해야합니까, 아니면 아무것도하지 않아야합니까? 일반적으로 CLR이 이와 비슷한 것을 보는 경우, 데이터를 해제하고 시나리오에서 잘못된 값으로 CoTaskMemFree를 호출해야한다고 가정합니다. – JaredPar

+0

(계속) 일반적으로 문자열을 마샬링하는 방법 (그리고 인라인 된 배열이 아님)에 대해 혼란 스러울 경우 IntPtr을 사용하여 문자열을 마샬링합니다. 이것은 일할 수있는 기회가 훨씬 더 많습니다. – JaredPar