将 C++ 结构体转换为 C# [英] Convert a C++ struct to C#

查看:112
本文介绍了将 C++ 结构体转换为 C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个与旧 C DLL 通信的 C# 应用程序.我查看了 C DLL 的头文件,看到了我需要在 C# 中创建的 2 个结构:

I am writing a C# application that communicates with an old C DLL. I looked at the header of the C DLL and saw 2 structures that I need to create in C#:

typedef struct
{
    char    user_field_name[MAXLENGTH];
    WORD    user_field_length;
    char    user_field_contents[80];
    char    user_field_requested[1];
    char    user_field_clear[1];
    char    user_field_attribute[1];
} U_FIELD_STRUCT;
typedef U_FIELD_STRUCT FAR * P_U_FIELD_STRUCT;

typedef struct
{
    char                user_begin_literal[7];
    char                user_screen_name[MNFRMSCRNAMELENGTH];
    char                key_to_be_sent[256]; 
    WORD                num_of_user_fields;
    U_FIELD_STRUCT      user_field[MAXFIELDCOUNT];
    char                user_end_literal[7];
} USER_FIELD_STRUCT;

在我的 C# 类中,我是这样写的:

In my C# class, I wrote them as follows:

    public const Int32 MAXLENGTH = 51;
    public const Int32 MAXTAGLENGTH = 80;
    public const Int32 MNFRMSCRNAMELENGTH = 5;
    public const Int32 MAXFIELDCOUNT = 100;
    public const Int32 MAXTAGCOUNT = 40;
    public const Int32 MAXSCREENCOUNT = 150;

    public const Int32 NO_SCREEN_DATA = 99;

    [StructLayout(LayoutKind.Sequential, Pack=4, CharSet=CharSet.Ansi)]
    public struct U_FIELD_STRUCT
    {
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=MAXLENGTH)]
        public char [] user_field_name;
        public short user_field_length;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=80)]
        public char [] user_field_contents;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=1)]
        public char [] user_field_requested;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=1)]
        public char [] user_field_clear;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=1)]
        public char [] user_field_attribute;
    };

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
    public struct USER_FIELD_STRUCT
    {
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=7)]
        public char [] user_begin_literal;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=MNFRMSCRNAMELENGTH)]
        public char [] user_screen_name;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=256)]
        public char [] key_to_be_sent;
        public short num_of_user_fields;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=MAXFIELDCOUNT)]
        public U_FIELD_STRUCT [] user_field;
        [ MarshalAs( UnmanagedType.ByValArray, SizeConst=7)]
        public char [] user_end_literal;
    };

当我在 C# 中初始化结构体时,我是这样做的:

When I initialize the struct in C#, I do it as follows:

        USER_FIELD_STRUCT UserFieldsData = new USER_FIELD_STRUCT();
        UserFieldsData.user_begin_literal = new char[7];
        UserFieldsData.user_screen_name = new char[MNFRMSCRNAMELENGTH];
        UserFieldsData.key_to_be_sent = new char[256];
        UserFieldsData.user_field = new U_FIELD_STRUCT[MAXFIELDCOUNT];
        UserFieldsData.user_end_literal = new char[7];
        for (int i = 0; i < MAXFIELDCOUNT; i++)
        {
            UserFieldsData.user_field[i].user_field_name = new char[MAXLENGTH];
            UserFieldsData.user_field[i].user_field_contents = new char[80];
            UserFieldsData.user_field[i].user_field_requested = new char[1];
            UserFieldsData.user_field[i].user_field_clear = new char[1];
            UserFieldsData.user_field[i].user_field_attribute = new char[1];
        }

问题是,当我调用我的方法时,我收到一条错误消息(基本上 DLL 必须验证字符串,并且它会发送一条消息,表明字符串不是它们应该是的).所以我安装了 VS6 并在调试模式下运行了 DLL.我查看了我发送的结构,字符串确实包含了我放入其中的数据(一些 char[] 没有数据,而另一些则包含 2 个字段的组合.)

The problem is that when I pinvoke my method, I am getting an error message (basically the DLL has to validate the strings, and it sends a message that the strings are not what they are supposed to be). So I installed VS6 and I ran the DLL in Debug mode. I took a look at the struct I was sending and the strings did have the data that I put in them (some of the char[] had no data and other had a combination of 2 of the fields.)

例如字段如果我这样设置字段:

For example, the field if I set the fields like this:

user_begin_literal="T0k0a10"
user_end_literal="T0k0b10"
user_screen_name="SC00"

当我在 VS6 中查看对象时:

When I look at the object in VS6:

user_begin_literal=" T0k0a10"
user_end_literal=""
user_screen_name="SC00"

我是否搞砸了结构设计?

Did I mess up my struct design?

推荐答案

在 C 中,一个字符只有 1 个字节,而在 C# 中它是 2 个字节.

In C, a char is only 1 byte, but in C# it is 2 bytes.

在 C# 中,使用 sbyte 映射到 C char(两者都是有符号的 8 位值),并使用 ushort 映射到一个C WORD(都是无符号的 16 位值).

In C# use sbyte to map to a C char (both are signed 8-bit values), and ushort to map to a C WORD (both are unsigned 16-bit values).

如果要将字符串值分配给结构的缓冲区之一,则应将其转换为 ASCII(或 UTF8,如果本机代码可以处理它),然后将字节复制到字段:

If you want to assign a string value to one of your struct's buffers, you should convert it to ASCII (or UTF8 if the native code can handle it), and then copy the bytes to the field:

void CopyStringToField(string value, sbyte[] field)
{
    int maxLength = field.Length;  // or field.Length - 1 if you need room for null terminator

    byte[] fieldValue = Encoding.ASCII.GetBytes(value);
    if (fieldValue.Length > maxLength)
        throw new ArgumentException("string too long for field.");

    int length = Math.Min(fieldValue.Length, maxLength);
    Array.Copy(fieldValue, 0, field, 0, length);

    // zero fill remaining bytes
    for (int i = length; i < field.Length; i++)
    {
        field[i] = 0;
    }
}

这篇关于将 C++ 结构体转换为 C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆