c# - 将指针编码到字符串数组

标签 c# pinvoke unmanaged marshalling

我在编码指向字符串数组的指针时遇到了一些问题。它看起来像这样无害:

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 并逐一提取字符串。

最佳答案

除了一个非常基本的字符串之外,编码任何东西都是复杂的,并且充满了难以发现的副作用。通常最好在结构定义中使用安全/简单的路由,并添加一些包装器属性来稍微整理一下。

在这种情况下,我会使用 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));
    }
}

关于c# - 将指针编码到字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1323797/

相关文章:

c# - P/Invoke 到 Mono 上动态加载的库

c# - 如何在 C# 中处理基类构造函数?

c# - 使用 FormsAuthentication.SetAuthCookie 存储加密字符串

c# - 调用 native 函数时最后一个参数出现损坏

c# - 如何将 COM 对象作为 IntPtr 传递给 P/Invoke 方法?

c# - 如何构造一个 try-catch-finally block 来处理 finally 内部的错误?

c# - 如何序列化具有属性的类

c# - WPF 中的 Application.ProductName 等价物?

c# - 使用 PInvoke 连接 C/C++ DLL 的调试断言失败

.net - 如何从非托管代码调用托管代码?