2009-08-24 62 views
5

我在編組指向字符串數組的指針時遇到了一些麻煩。它看起來無害的像這樣:封裝指向字符串數組的指針

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

這實際上是嵌入到另一個結構裏面是這樣的:

typedef struct 
{ 
    UnmanagedStruct umgdStruct; 
} Outerstruct; 

非託管代碼回調到託管代碼,返回Outerstruct作爲一個IntPtr與分配的內存和值填充。

管理世界:

[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,所以編組時的錯誤有點奇怪。 – 2009-08-24 18:13:30

+0

噢,如果你有public string [] listOfStrings,它的ByValArray會讓我認爲有所不同。 – 2009-08-24 18:14:18

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 2009-08-24 18:13:37

+0

@Dilip,選擇你的代碼片段並按CTRL + K。這將通過縮進一切來修復格式化4 spcaes – JaredPar 2009-08-24 18:24:37

+0

@Jared:快速跟進。如果我使用UnmanagedType.LPArray,代碼會繼續炸彈。只有UnmanagedType.ByValArray有效。我現在明白了KeeperOfTheSoul在他/她的評論中暗示了什麼。 – Dilip 2009-08-24 21:40:15