我实际上是一名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);
答案 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(但没有任何保证),给出:
其中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。