【问题标题】:Marshal NOT 0 terminated stringMarshal NOT 0 终止字符串
【发布时间】:2012-07-19 08:30:31
【问题描述】:

我有以下非托管结构。

struct MyNativeStruct_Foo
{   
 char product_name[4];
 char product_model[2];
}

还有托管的等价物

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyManagedStruct_Foo
{
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 4)]
    public string product_name;

    [MarshalAs(UnmanagedType.LPStr, SizeConst = 2)]
    public string product_model;
}

不幸的是,stings 不是以 null 结尾的。使用了产品名称的全部 4 个字符。如果我用“LPStr”定义托管结构,则字符串必须以 0 结尾。

还有其他方法来定义托管结构吗?可以定义自定义 Marshaller 属性吗?还是您有其他想法?

注意; 本机结构无法更改。

谢谢

安伯格

[编辑] 改为 LPStr(评论 Jason Larke)

【问题讨论】:

  • 请注意,您的 C++ 声明使用char,而不是char_t,因此您的声明不需要TStr。另外,您将结构的 CharSet 显式设置为ANSI :)

标签: c# c++ marshalling


【解决方案1】:

您可以更改编组以将字符串视为bytess 的固定大小数组,然后使用Encoding 类将字节转换为托管字符串。

[StructLayout(LayoutKind.Sequential)]
public struct MyManagedStruct_Foo
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public byte[] product_name;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
    public byte[] product_model;

    public string GetProductName()
    {
        return System.Text.Encoding.ASCII.GetString(this.product_name);
    }

    public string GetProductModel()
    {
        return System.Text.Encoding.ASCII.GetString(this.product_model);
    }
}

不完全是世界上最性感的结构,但它应该可以满足您的需求。

【讨论】:

  • 我用自定义编组器和自定义 Marshaller 属性做了一些尝试,因为这样的字符串经常在不同的结构中。但是我在将字符串长度传递给自定义 Marshaller 时遇到了问题。您的解决方案将产生更多代码行,但效果很好。谢谢
  • 我从来没有尝试过从非托管内存中编组一个固定长度的字符串,这就是为什么我发布了一个简单的byte 解决方案。如果我今晚有时间,我会尝试弄乱结构,看看我是否能以更好的方式完成它。
猜你喜欢
  • 2014-02-01
  • 2014-12-03
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
相关资源
最近更新 更多