C ++ memcpy到c#等价

时间:2014-03-12 20:43:13

标签: c# c++

我实际上是一名java开发人员,但对于一个不太重要的项目,我试图将lib从c ++转换为c#。我在ansi C中有一个小背景但是这段代码让我感到困惑

    long hfzWriteHeader(hfzFile* fs, hfzHeader& fh) {

        // copy header into buffer
        char HeaderBuf[28];
        long HeaderBufPos = 0;
        sprintf(HeaderBuf+HeaderBufPos, "HF2"); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.FileVersionNo), 2); HeaderBufPos+=2;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.nx), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.ny), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.TileSize), 2); HeaderBufPos+=2;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.Precis), 4); HeaderBufPos+=4;
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.HorizScale), 4); HeaderBufPos+=4;

        // put extended header into a buffer
        char* pExtHeaderData = 0;
        long rval = hfzHeader_EncodeExtHeaderBuf(fh, &pExtHeaderData);
        if(rval<0) return rval;

        // now write in header length of ext header
        hfzMemcpy(HeaderBuf+HeaderBufPos, &(fh.ExtHeaderLength), 4);    

            HeaderBufPos+=4;

        // swap byte order if required (files use little endian)
        if(LIBHFZ_BYTEORDER_BIGENDIAN==hfzByteOrder) {
        HeaderBufPos = 4; // skip "HF2\0" string

           hfzByteSwap(HeaderBuf+HeaderBufPos, 2); HeaderBufPos+=2; // FileVersionNo
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // nx
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // ny
           hfzByteSwap(HeaderBuf+HeaderBufPos, 2); HeaderBufPos+=2; // TileSize
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // Precis
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // HorizScale
           hfzByteSwap(HeaderBuf+HeaderBufPos, 4); HeaderBufPos+=4; // ExtHeaderLength
       }

   // write header
   if(28!=hfzWrite(fs, HeaderBuf, 28)) 
       return LIBHFZ_ERROR_WRITE_HEADER_FAILED;

// write extended header
   if(pExtHeaderData) {
       if(fh.ExtHeaderLength!=hfzWrite(fs, pExtHeaderData, fh.ExtHeaderLength)) {
           hfzFree(pExtHeaderData);
           return LIBHFZ_ERROR_WRITE_EXTHEAD_FAILED;
       }
       hfzFree(pExtHeaderData);
   }

   return LIBHFZ_STATUS_OK;
   }

我相信它正在尝试在内存中构建一个char数组(字符串?),以便稍后将其写入二进制文件。这是文件类型的标题部分。在java中,我可能只是使用字符串构建器然后追加。但是我确实认为一些字节操作正在进行,字符串的每个部分都是字节数,但我想知道fh.nx是短的,如果short只是值1,结果会是什么?它是&#34; 1&#34;或&#34; 0001&#34;。这是令我困惑的部分。

我对缺乏C知识的任何帮助或启发表示赞赏

似乎将整个函数放在这里而不仅仅是部分函数会更好,因为稍后会出现BIGENDIAN情况。对不起格式化但在stackoverflow上正确处理是神经破坏。

=========初步结果==============

所以我最终使用John Skeet的课来照顾这个结尾,然后想出了这个...我只是想知道我不会错过这一切。我是基于c ++方法结构重写的,但是很多方法都是如此低级别,以至于它们在更高级别的C#中可用...现在我记得为什么我去了Java而不是C.I& #39; m很快就与所有指针和内存处理混淆了!

仅供参考,这是我尝试编写和转换库的文件格式: http://www.bundysoft.com/docs/doku.php?id=l3dt:formats:specs:hf2

    // copy header into buffer
    MiscUtil.Conversion.EndianBitConverter endian = MiscUtil.Conversion.EndianBitConverter.Big;
    if (BitConverter.IsLittleEndian)
    {
        endian = MiscUtil.Conversion.EndianBitConverter.Little;
    }

    MemoryStream buffer = new MemoryStream();
    EndianBinaryWriter writer = new EndianBinaryWriter(endian, buffer);
    writer.Write("HF2");
    writer.Write(fh.FileVersionNo);
    writer.Write(fh.nx);
    writer.Write(fh.ny);
    writer.Write(fh.TileSize);
    writer.Write(fh.Precis);
    writer.Write(fh.HorizScale);

3 个答案:

答案 0 :(得分:4)

这是为结构化数据执行一种二进制序列化。查看BinaryWriter以了解.NET中的类似功能。这可以附加到任何流,但是如果要使用字节数组作为后备存储(如C代码中那样),则可以使用MemoryStream

另请注意(如另一张海报所述),您可能需要注意Endian-ness和其他特定于平台的问题,至少假设您希望与C程序二进制兼容。如果不知道用于原始程序的平台以及如何与它进行互操作,如果有的话,很难说更多。例如,数据是否保存到您希望能够加载的文件中?


更新:

根据您的编辑,看起来原始代码是Endian-aware。您可以使用BitConverter.IsLittleEndian检查平台的Endian-ness,并在C#代码中对字节数组进行等效的交换调整。

如果您知道自己在Windows上运行并且不想担心跨平台支持,那么您可以假设BinaryWriter是Little Endian(实际上,即使在Big Endian上它也可能是Mono中的Little Endian)平台,但我不确定。)如果您想要安全,可以查看Jon Skeet处理必要转换的实用程序类。

答案 1 :(得分:1)

取决于sizeof(短)以及机器是大端还是小端。 sizeof(短)可能是2(但没有任何保证),给出:

  • big-endian:00 01 xx xx
  • little-endian:01 00 xx xx

其中xx是一些随机垃圾。 00表示值为0x00的字节; 01是一个值为0x01的字节。

为什么代码复制四个字节是个谜......

但整件事情太可怕了:它会导致特定于平台的(我很确定,但不要引用我)未定义的行为。

更新:给定OP的更新(vars是long而不是short,以及处理endianness的附加代码),我的上一个声明现在有点无根据。

答案 2 :(得分:0)

[DllImport("kernel32.dll")]
private static extern void RtlMoveMemory(IntPtr dest, IntPtr src, int byteCount);

这是一个用于指针的真实内存副本,应该适用于所有版本的Windows。