Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
转换代码c++;要读c#,请向全班同学朗读_C#_C++ - Fatal编程技术网

转换代码c++;要读c#,请向全班同学朗读

转换代码c++;要读c#,请向全班同学朗读,c#,c++,C#,C++,我有一节课 class DataqFmt { public: unsigned short SR_number; unsigned short SR_numerator; unsigned char offset; unsigned char nbytes; short hdr_bytes; unsigned long dat_bytes; char dummy[1144]; }; 代码

我有一节课

class DataqFmt 
{
public:
    unsigned short  SR_number;
    unsigned short  SR_numerator;
    unsigned char   offset;
    unsigned char   nbytes;
    short       hdr_bytes;
    unsigned long   dat_bytes;
        char        dummy[1144];
};

代码C++:

afl = fopen(path, "rb");
DataqFmt dataqstr;
fread ((char*) &dataqstr, sizeof (dataqstr), 1, afl);

如何将此代码转换为C++?请帮助我< /P> < P>我假设编写这个文件的C++应用程序是为Win32 x86编译的,在Win32 x86上运行。这允许我对
DataqFmt
的安排方式做出假设。如果这些假设是错误的,可以使用和相关属性的各种选项(如和)来调整它们

首先,我们将使用与
DataqFmt
布局相同的C#结构:

[StructLayout(LayoutKind.Sequential)]
struct DataqFmtCs
{
    public ushort SR_number; // assuming the C++ type unsigned short is 2 bytes
    public ushort SR_numerator;
    public byte offset; // assuming the C++ type unsigned char was an unsigned and 1 byte
    public byte nbytes;
    public short hdr_bytes; // assuming the C++ type short was 2 bytes
    public uint dat_bytes; // assuming the C++ type unsigned long was 4 bytes
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1144)]
    public sbyte[] dummy; // assuming the C++ type char was signed and 1 byte
}
使用这种结构,我们现在需要进行文件I/O以获取原始字节

int dataqfmtSize = Marshal.SizeOf(typeof(DataqFmtCs));
var buffer = new byte[dataqfmtSize];
using (var fs = File.OpenRead("path\\to\\the\\file")) {
    int bytesRead = fs.Read(buffer, 0, buffer.Length);
    if (bytesRead != buffer.Length) {
        // handle this
    }

    DataqFmtCs someThing = GetDataqFmtFromBuffer(buffer);
}
最后,我们有一个转换例程
GetDataqFmtFromBuffer

private static DataqFmtCs GetDataqFmtFromBuffer(byte[] buffer) {
    GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    try {
        return (DataFmtCs)Marshal.PtrToStructure(
            handle.AddrOfPinnedObject(),
            typeof(DataFmtCs));
    } finally {
        handle.Free();
    }
}
正在做绝大多数的转换工作。代码的其余部分只是定义结构并执行基本的.NET文件I/O


另一个选择——如果您使用的是一个与平台无关的、有良好文档记录的协议,这通常是一个很好的解决方案,因为您经常需要执行转换——就是编写一个反序列化例程,使用。我将把它作为练习。

如果你使用VisualStudio,你也可以导入C++代码并编译成CLR库,以供任何其他.NET程序集引用。如果你需要C++代码运行速度快,这是个好主意。

如果你愿意承认C++ Frad()是天生的脆弱和不可移植的,最好写一个抽象层来读取和写入代码数据类型,例如这样的格式是有用的:

// returns true on success, false on EOF
public static bool Read(Stream stm, out int val)
{ /* ... */ }

public static bool Read(Stream stm, out short val)
{ /* ... */ }
然后,您可以编写类似以下内容的代码:

if (!Read(stm, out _someMember))
    throw SomeException(); // or return a fail code
if (!Read(stm, out _someOtherMember))
    throw SomeException();
或者在我的一些代码中,我编写了一个方法,给定一个对象、一个流和一个字段或属性的名称,读取适当大小的值并设置成员(如果找不到,则抛出一个异常),然后编写一个类似的方法来处理一个对象和一组名称(或者实际上是可变数量的字符串参数,因此初始化可以如下所示:

    public static TTHorizontalHeader FromStream(Stream stm)
    {
        TTHorizontalHeader header = new TTHorizontalHeader();
        if (!Reader.ReadType(stm, header,
            "TableVersion", "Ascender", "Descender", "LineGap", "AdvanceWidthMax", "MinLeftSideBearing",
            "MinRightSideBearing", "XMaxExtent", "CaretSlopeRise", "CaretSlopeRun", "CaretOffset", "Reserved0",
            "Reserved1", "Reserved2", "Reserved3", "MetricDataFormat", "NumberOfHMetrics"))
            return null;
        return header;
    }

<>但是你会说,“C++运行速度会不会更快,因为它只做一个Frad()?”我回答说:"Endianess、数据类型大小、结构填充和对象布局的更改是不以性能为幌子继续传播同一脆弱代码的充分理由。任何合适的缓冲流无论如何只会进行一次实际读取,而读取工作由一个公正的机器人完成。除了I/O成本外,无论是否缓冲,都将使t反射和字符串迭代的成本。

如果你需要它来处理已经被C++从该格式中删除的现有文件,那将是棘手的。