2008-12-15 2 views
41

관리되지 않는 DLL에서 메서드를 호출하는 일부 C# 코드를 작성하려고합니다. DLL에있는 함수의 프로토 타입은 다음과 같습니다 C#에서P * char *를 반환하는 C 함수에 대한 호출 *

extern "C" __declspec(dllexport) char *foo(void); 

이, 내가 먼저 사용 :

[DllImport(_dllLocation)] 
public static extern string foo(); 

은 표면에 작동하는 것 같다,하지만 난 런타임시 메모리 손상 오류를 받고 있어요. 나는 올바른 기억을 가리키고 있다고 생각하지만, 이미 해제되었다.

"P/Invoke Interop Assistant"라는 PInvoke code gen 유틸리티를 사용해 보았습니다. 그것은 저에게 산출을주었습니다 :

[System.Runtime.InteropServices.DLLImportAttribute(_dllLocation, EntryPoint = "foo")] 
public static extern System.IntPtr foo(); 

이것이 맞습니까? 그렇다면이 IntPtr을 C#의 문자열로 변환하려면 어떻게해야합니까?

답변

67

이 값을 IntPtr로 반환해야합니다. PInvoke 함수에서 System.String 형식을 반환하면 매우주의해야합니다. CLR은 네이티브 표현에서 관리되는 메모리로 메모리를 전송해야합니다. 이것은 쉽고 예측 가능한 작업입니다.

문제는 foo()에서 반환 된 기본 메모리와 관련이 있습니다. CLR은 직접 따라서

가 마샬링됩니다

  1. 네이티브 메모리가 기본 메모리가 CoTaskMemAlloc으로 할당 된
  2. 해제 할 필요가있는 문자열 형식을 반환하는 PInvoke를 기능에 대한 다음과 같은 두 가지 항목을 가정 문자열을 읽고 네이티브 메모리 blob에서 CoTaskMemFree를 호출합니다. 실제로이 메모리를 CoTaskMemAlloc으로 할당하지 않으면 응용 프로그램에서 충돌이 발생할 수 있습니다. 여기에 정확한 의미를 얻을 당신은 IntPtr입니다에게 직접 반환해야합니다 위해

    . 그런 다음 관리되는 문자열 값에 도달하기 위해 Marshal.PtrToString *를 사용합니다. 네이티브 메모리를 해제해야하지만 foo의 구현에 따라 달라질 수 있습니다.

19

Marshal.PtrToStringAuto 메서드를 사용할 수 있습니다.

IntPtr ptr = foo(); 
string str = Marshal.PtrToStringAuto(ptr); 
+1

이것은 나를 위해 일했습니다. 내가해야만 한 유일한 변화는'PtrToStringAnsi'에'PtrToStringAuto'이었습니다. 그렇지 않으면 몇개의 중국어 문자가 있습니다. – 3vts

관련 문제