2009-08-24 3 views
5

문자열 배열에 대한 포인터를 마샬링하는 데 문제가 있습니다.문자열 배열에 마샬링

typedef struct 
{ 
    char* listOfStrings[100]; 
} UnmanagedStruct; 

이 실제로이 같은 다른 구조의 내부에 포함됩니다 : 그것은이 같은 무해한 보이는

typedef struct 
{ 
    UnmanagedStruct umgdStruct; 
} Outerstruct; 

관리되지 않는 코드를 다시 관리 코드로 호출하고 채워 할당 된 메모리와 가치를 가진를 IntPtr로 Outerstruct 반환 .

관리 세계 :

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public string[] listOfStrings; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct Outerstruct 
{ 
    public UnmanagedStruct ums; 
} 

public void CallbackFromUnmanagedLayer(IntPtr outerStruct) 
{ 
    Outerstruct os = Marshal.PtrToStructure(outerStruct, typeof(Outerstruct)); 
    // The above line FAILS! it throws an exception complaining it cannot marshal listOfStrings field in the inner struct and that its managed representation is incorrect! 
} 

listOfStrings를 단순히 IntPtr로 변경하면 Marshal.PtrToStructure가 작동하지만 이제는 listOfStrings로 추출하여 문자열을 하나씩 추출 할 수 없습니다.

답변

1

확인 .. 내가이 일을 가지고 보인다 문자열. 그것은을 IntPtr은 []

이 작동하는 것 같다으로 마샬링해야합니다

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=100)] 
    public IntPtr[] listOfStrings; 
} 

for (int i = 0; i < 100; ++i) 
{ 
    if (listOfstrings[i] != IntPtr.Zero) 
     Console.WriteLine(Marshal.PtrToStringAnsi(listOfStrings[i])); 
}  
+0

ByValArray == 현재 위치의 배열, LPArray == 배열에 대한 포인터. SizeConst가 여전히 LPArray와 함께 작동해야하기 때문에 마샬링시 오류가 조금 이상합니다. –

+0

오, 그건 당신이 공공 문자열 [] listOfStrings, 내가 믿는 차이를 만드는 ByValArray가있는 경우에도 작동합니다. –

4

매우 기본적인 문자열을 마샬링하는 것은 복잡하고 자리를 잡기가 어려운 경우가 많습니다. 일반적으로 구조체 정의에서 안전하고 간단한 경로를 사용하고 약간의 래퍼 속성을 추가하여 정리하는 것이 가장 좋습니다. 내가 IntPtr입니다 배열로 이동하고 변환하는 래퍼 속성을 추가 할이 경우

그들

[StructLayout(LayoutKind.Sequential)] 
public struct UnmanagedStruct 
{ 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] 
    public IntPtr[] listOfStrings; 

    public IEnumerable<string> Strings { get { 
     return listOfStrings.Select(x =>Marshal.PtrToStringAnsi(x)); 
    } 
} 
+0

제라드 감사의 유효성을 확인! 나는 당신의 것을보기 바로 전에 내 자신의 질문에 대한 답을 올렸습니다. 한 가지 질문 - 코드에서 게시물의 형식을 지정하려면 어떻게해야합니까? 그들은 모두 엉망으로 보였고 누군가는 항상 그것을 편집하고 고쳐야 만했습니다. – Dilip

+0

@Dilip 코드 스 니펫을 선택하고 CTRL + K를 누릅니다. 이렇게하면 모든 문자를 들여 쓰기하여 서식이 수정됩니다. – JaredPar

+0

@ Jared : 빠른 후속 조치. UnmanagedType.LPArray를 사용하면 코드가 계속 폭탄을 만듭니다. UnmanagedType.ByValArray 만 작동합니다. 나는 KeeperOfTheSoul이 그의 의견에서 암시하고있는 것을 이해하고있다. – Dilip