- 내가해야합니까 :이 방법으로 문자열을 전달할 때 어떻게해야합니까 지금
[DllImport("NativeLib")] static extern void do_something(string str);
:
는 또한,이 함수를 호출하는 C#에서이 서명을 문자열 (
GCHandle.Alloc()
)을 고정 시키십시오 (또는 마샬 러가 사본을 작성하고 있습니까)? - 고정해야하는 경우 '원래'문자열 (즉,
GCHandle.Alloc()
에 전달 된 문자열)을 전달합니까? 또는 반환 값GCHandle.AddrOfPinnedObject()
을 전달해야합니까? - 이 경우 올바른 데이터 형식 (
do_something
)이string
입니까? 또는 대신IntPtr
을 사용해야합니까?
답변
interop 경계를 통해 포인터를 저장하는 것은 정말 나쁜 아이디어입니다. 대신 C 코드를 수정하여 문자열의 복사본을 만들 수있는 모든 작업을 수행하십시오.
upvoted 대답에서 제안 된대로 문자열을 고정하지 않으면 pinvoke marshaller가 문자열을 char *로 변환하고 변환 된 문자열을 네이티브 호출 후에 포인터를 무효화해야합니다. 너 스스로 문자열을 마샬링해야한다. 인수를 IntPtr로 선언하고 Marshal.StringToHGlobalAnsi()를 사용하여 포인터 값을 만듭니다.
또는 Marshal.StringToCoTaskMemAnsi()를 사용하면 COM 힙에서 할당됩니다. 당신의 진짜 문제는 문자열을 풀어내는 훌륭한 시나리오가 아닙니다. C 코드는 할당 방법을 모르기 때문에 문자열을 해제 할 수 없습니다. C 코드가 포인터로 완료되는시기를 알 수 없기 때문에 C# 코드는 문자열을 해제 할 수 없습니다. 그래서 문자열을 복사하는 것이 중요합니다. 이 전화를 몇 번만하면 메모리 누출이 발생할 수 있습니다.
비 관리 코드가 문자열을 복사하는 대신 포인터를 저장한다는 점을 감안할 때 GCHandle.Alloc()을 사용하여 수동으로 문자열 복사본을 만들어 IntPtr로 전달하는 것이 좋습니다.
그러면 전달 된 메모리 블록의 수명을 관리 할 수 있습니다. 메모리 블록이 완료되면 GCHandle을 통해 메모리 블록을 해제합니다.
당신이 뭘 제안하는지 분명하지 않습니다. 'GCHandle.Alloc'으로 문자열을 고정시키고 싶습니까? 그건 나쁜 생각이야. – CodesInChaos
죄송합니다. 답변이 불완전합니다. GCHandle.Alloc()을 사용하여 문자열에 대한 메모리를 얻은 다음 Marshal.AllocHGlobal()을 사용하여 전역 메모리를 할당하고 Marshal.Copy()를 사용하여 문자열을 복사합니다. 그러나 한스 (Hans)는 StringToHGlobalAnsi를 제안했다. –
"어딘가에 문자열을 저장합니다"라고 말하면 문자열의 사본을 만들거나 포인터를 저장한다는 의미입니까? 그것은 당신의 질문에 대한 답에 큰 차이를 만듭니다. 포인터를 저장하는 중이라면 GCHandle.Alloc()을 사용해야합니다. 마샬 러는 그렇지 않으면 TEMPORARY 복사본을 만듭니다. –
포인트를 직접 저장합니다 (사본이 아님). –
interop 시그니처의 문자열 매개 변수를'IntPtr' 또는'byte *'로 대체해야합니다. – CodesInChaos