我正在将一些C ++代码转换为C#。我想将字节数组重新解释为结构,就像在C ++中可以轻松做到的那样。 我宁愿避免序列化或反射,而只使用指针,我想知道这是否可能。
这是我要从文件重新解释的结构:
public struct MS_DOS_Stub
{
UInt16 e_magic; // Magic number
UInt16 e_cblp; // Bytes on last page of file
UInt16 e_cp; // Pages in file
UInt16 e_crlc; // Relocations
UInt16 e_cparhdr; // Size of header in paragraphs
UInt16 e_minalloc; // Minimum extra paragraphs needed
UInt16 e_maxalloc; // Maximum extra paragraphs needed
UInt16 e_ss; // Initial (relative) SS value
UInt16 e_sp; // Initial SP value
UInt16 e_csum; // Checksum
UInt16 e_ip; // Initial IP value
UInt16 e_cs; // Initial (relative) CS value
UInt16 e_lfarlc; // File address of relocation table
UInt16 e_ovno; // Overlay number
#region ReservedWords
UInt16 e_res1; // Reserved words
UInt16 e_res2; //Cant initialize an array in a struct in C#
UInt16 e_res3;
UInt16 e_res4;
#endregion
UInt16 e_oemid; // OEM identifier (for e_oeminfo)
UInt16 e_oeminfo; // OEM information; e_oemid specific
#region ReservedWords2
UInt16 e_res5; // Reserved words
UInt16 e_res6;
UInt16 e_res7;
UInt16 e_res8;
UInt16 e_res9;
UInt16 e_res10;
UInt16 e_res11;
UInt16 e_res12;
UInt16 e_res13;
UInt16 e_res14;
#endregion // Reserved words
UInt32 e_lfanew; // File address of new exe header
};
这是我正在调用的方法:
static unsafe Dictionary<string, UInt32> dumpSymbols(ref byte[] bin)
{
fixed (byte* pBin = bin)
{
MS_DOS_Stub* stub = (MS_DOS_Stub*)(pBin);
if(stub->e_magic != IMAGE_DOS_SIGNATURE)
{
throw new FileLoadException("Error, Invalid file. DOS Signature is incorrect.");
}
// ...
}
return null;
}
我希望能够简单地使用stub->member
或stub.member
,但是存根似乎没有成员。
答案 0 :(得分:0)
一件事是,当您像声明结构一样声明结构时,结构的所有成员都变为私有。因此,从外部看它似乎没有成员。这很容易解决,只需在每个成员声明之前添加public
:
struct MS_DOS_Stub
{
public UInt16 e_magic; // Magic number
// and so on and so forth
将字节数组重新解释为结构是另一回事。据我了解,您从文件中读取数据作为字节数组,然后将其转换为结构。您的代码,尤其是这部分
fixed (byte* pBin = bin)
{
MS_DOS_Stub* stub = (MS_DOS_Stub*)(pBin);
对我不好。不仅因为它使用了指针,这不是C#可以做的最好的事情。如果考虑到这一点,则此方法(无论是否以C#或C ++实现)都依赖于内存中的结构布局,小端/大端架构。通常,您不能将内存的一部分转储到文件中然后再读回(可能在另一台计算机上!),并期望它是结构的正确表示。
我不知道此解决方案既简单又健壮。在您的情况下,我将只使用BitConverter来逐一提取我所迷惑的结构的各个部分。喜欢
stub.magic = BitConverter.ToInt16(bin, 0);
stub.e_cblp = BitConverter.ToInt16(bin, 2);
.....
stub.e_lfanew = BitConverter.ToInt32(bin, 60);
对于一个简单的任务,此代码可能很长且很冗长,但是可以保证不管您的环境如何,它都可以工作。而且,这样一来,您就不会有任何unsafe
指针欺骗的代码,如果您使用.Net进行编程,这是一件好事。