C++ 转换为 C#

Posted

技术标签:

【中文标题】C++ 转换为 C#【英文标题】:C++ Conversion To C# 【发布时间】:2013-08-05 21:34:13 【问题描述】:

我遇到了以下情况:

struct object1  

    bool a:1;
    bool b:1;
    uint8_t c:2;
    bool d:1;
    abc  e:3;

    uint16_t header;
    uint8_t footer;
    uint8_t mid[4];

我可能不知道语法,但在 C# 中玩位并不像 C++ 那样简单。我使用了 BitArray 和 BitConverter 类来制作填充数据的方法,但我遇到了问题:

object1 * rqr = (object1  *) &Msg.Data[2];

基本上,他们将对象转换为字节数组。我所做的每一次搜索都需要序列化,但要真正转换上面的行,我不能有任何额外的元数据或任何东西。

我真的很想创建一个指向内存位置的指针并将该位置“投射”到所述对象。这可能吗?如果没有,是否有解决此问题的方法?我无法想象这个级别的位操作被完全排除在外。在假设之前,我会默认我只是不知道。

编辑:: 我知道 C# 不允许指向管理类型的指针。我要问的是有没有办法说:

Byte[] ayData = new Byte[8];
ObjectOfSize8 nObject =  (ObjectOfSize8)ayData;

我知道上面的方法行不通,但是,如果你足够聪明,可以理解对象的内存大小,语言中是否有允许数据转换的东西?

【问题讨论】:

根据&Msg.Data[2] 返回的内容,该行可能违反严格的别名规则。只有char* 是一个特例。此外,C# 不允许指向托管类型的指针。为什么不直接使用字节数组并创建一个类来处理创建和提取消息? 我试图严格控制代码的转换;具有讽刺意味的是,“Data”(Data[2])结构是一个大字节数组,所以 char* 实际上是返回的。数据来回传递。这个问题的目的是双重的。数据正在通过许多被投射到数据上的结构进行操作。编写函数来处理数据的操作需要我一段时间,所以我想知道是否有一种方法可以对数据数组进行强制转换。第二个是简单地看看是否有办法将任意数据“调用”为对象。 你为什么要在 C# 中这样做?它真的不适合这种事情。您最好在 C++ 中执行此操作,然后转移到非位域结构,然后将其返回到 C#。 不,您不能将结构或任何对象覆盖到 C# 中的字节数组上。只需解析缓冲区,并不难。 @BlndLeadingDef:因为经常有人带着 90% 的“解决方案”来到这里,并要求我们解决最后 10% 的问题。几乎同样,最后 10% 是没有意义的,所以我们需要知道你实际上想要完成什么,以提供一个你可能没有考虑过的更好的选择。 (在整个“最后 10% 毫无意义”的事情上归功于 R. Chen。这种情况经常发生,他写了一篇关于它的博客文章)。你想要做什么并不重要;你不能在 C# 中以这种方式解决你的问题。 【参考方案1】:

您可以使用为您处理位移和屏蔽的结构来解决您的位域问题:

[StructLayout(LayoutKind.Sequential, Size=1)]
public struct BitField8

    private byte _bits;

    private static readonly byte[] Masks = new byte[]  0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff ;
    public BitField8(int val)
    
        _bits = (byte) val;
    

    public byte Get(int bit, int length = 1)
    
        int shift = bit + length - 1;
        return (byte) ((_bits >> shift) & Masks[length-1]);
    

    public void Set(int bit, int length, int val)
    
        int mask = Masks[length-1];
        int shift = bit + length - 1;
        val = (val & mask) << shift;
        mask = ~(mask << shift);
        _bits = (byte)((_bits & mask) | val);
    

所以在你的例子中:

bool a:1;
bool b:1;
uint8_t c:2;
bool d:1;
abc  e:3;

您可以通过调用 Set(0, 1, 1) 来设置 a(将 a 设置为 1)。

要给c 赋值3,你可以调用Set(3, 2, 3)。 (c 占用位 2 和 3)。

这基本上复制了 C++ 位域的功能,尽管我承认我的位顺序可能有误。我真的不知道 C++ 编译器将a 放在第 0 位还是第 7 位。

您可以对 16 位、32 位和 64 位位域执行类似操作。

所以你的结构将包含:

BitField8 myBitfield;

【讨论】:

吉姆感谢您的回答。我非常感谢您花时间提供如此详细的回复。我想看看 C# 中是否有等效的语法或方法来处理大量转换。大卫的钉扎想法很有趣。这确实回答了如何以简洁明了的方式处理位域操作的情况。【参考方案2】:

C# 中的类型转换无法满足您的要求。我怀疑做你需要的最干净的方法可能是固定 C# 结构。然后你就有了一个 IntPtr,你可以使用 Marshal.Copy 来复制到字节数组和从字节数组复制。

至于位域,需要使用按位移位、按位或和按位与操作进行管理。

【讨论】:

感谢您的消息,我想将 Ed S. 的回答标记为正确,因为他最初是提到它的人。如果他没有发布答案,我会在一小时内将您的答案标记为此类。 Ed S. 不建议固定和复制,FWIW。他的建议不同。 而且我不会以任何方式发布答案:)。接受这个。 按要求;谢谢你们的帮助。感谢您的回复和支持。

以上是关于C++ 转换为 C#的主要内容,如果未能解决你的问题,请参考以下文章

将代码从 C++ 转换为 C# 的问题

C++ 函数转换为 C# 函数

将项目从 C++ 转换为 C#

将指向成员的 C++ 指针转换为 C#

将 Suprema Biostar C++ 代码转换为 C#

将错误级别分析的 C++ 实现转换为 C#