简体   繁体   English

在C ++ / C之间传递结构中的字符串/数组#

[英]Passing strings/arrays within structures between C++/C#

I am passing a struct from C# to C++. 我将结构从C#传递给C ++。

C# code: C#代码:

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct Data
{
[MarshalAs(UnmanagedType.U4)]
public int number;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public int[] array;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string buffer;
}

C++ code: C ++代码:

struct Data
{
public:
    int number;
    int array[5];
    char buffer[512];
    //char *buffer;
};

The above method works fine. 上面的方法工作正常。 But Instead if I use pointers to handle data in C++ I am getting error as: 但相反,如果我使用指针来处理C++数据,我会收到错误:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory 未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存

struct Data
{
public:
    int number;
    int *array;
    char *buffer;
};

Why cant I handle with pointers here? 为什么我不能在这里处理指针? Is handling this case via pointers advantageous? 通过指针处理这种情况有利吗?

The first struct works because it allocates array in the struct. 第一个结构是有效的,因为它在结构中分配数组 The second is problematic because it only allocates an int pointer and char pointer (which is sizeof(void*) depends on your platform) in the struct, and not an int array. 第二个是有问题的,因为它只在结构中分配一个int指针和char指针( sizeof(void*)取决于你的平台),而不是int数组。 If you insist on using pointers you have to allocate and deallocate the memory on your own (ie new and delete[] ). 如果你坚持使用指针,你必须自己分配和释放内存(即newdelete[] )。

The problem is how your data represented in memory. 问题是你的数据在内存中的表现方式。

Let's assume you have an instance of c# structure that marshals to unmanaged code or even file. 假设您有一个c#结构实例,它将编组为非托管代码甚至文件。

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct Data
{
[MarshalAs(UnmanagedType.U4)]
public int number = 5;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public int[] array = {0, 1, 2, 3, 4};

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]

public string buffer = "Happy new Year";
}

According to this, your memory layout will be like this (in hex-like view): 根据这个,你的内存布局将是这样的(在类似十六进制的视图中):

05 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00
03 00 00 00 04 00 00 00
00 48 00 61 00 70 00 70 
00 79 00 20 00 6E 00 65 
00 77 00 20 00 59 00 65 
00 61 00 72

Here we have first four bytes "05 00 00 00", which means number "5" in memory for your "number" variable. 这里我们有前四个字节“05 00 00 00”,这意味着你的“数字”变量在内存中的数字“5”。 (Notice that these bytes in reversed order because Intel architecture is LittleEndian, see Endiannes for details) (请注意,这些字节的顺序相反,因为Intel架构是LittleEndian,有关详细信息,请参阅Endiannes

Then we have next five integers as "00 00 00 00" = 0, "01 00 00 00" = 1, "02 00 00 00" = 2, "03 00 00 00" = 3, "04 00 00 00" = 4 for array named "array". 然后我们接下来的五个整数为“00 00 00 00”= 0,“01 00 00 00”= 1,“02 00 00 00”= 2,“03 00 00 00”= 3,“04 00 00 00”= 4表示名为“array”的数组。

And the string "buffer" represents like this: 字符串“buffer”表示如下:

"00 48" = H
"00 61" = a
"00 70" = p
"00 70" = p
"00 79" = y
"00 20" = <space>
"00 6E" = n
"00 65" = e
"00 77" = w
"00 20" = <space>
"00 59" = Y
"00 65" = e
"00 61" = a
"00 72" = r

There is some trick that .NET always use Unicode to store it's string variables. 有一些技巧,.NET总是使用Unicode来存储它的字符串变量。 Every Unicode character has it's two-byte representation. 每个Unicode字符都有两个字节的表示形式。

Now, for this C++ struct 现在,对于这个C ++结构

struct Data
{
public:
    int number;
    int array[5];
    char buffer[512];
    //char *buffer;
};

sizeof(int) is 4. So the content of memory for variable "number" = "05 00 00 00" which is number five. sizeof(int)是4.因此变量“number”=“05 00 00 00”的内存内容为5。 array[0],array 1 ,array[2],array[3],array[4] lay out on memory blocks "00 00 00 00" = 0, "01 00 00 00" = 1, "02 00 00 00" = 2, "03 00 00 00" = 3, "04 00 00 00" = 4. Everything else remains to buffer[512] variable. array [0],array 1 ,array [2],array [3],array [4]布局在内存块“00 00 00 00”= 0,“01 00 00 00”= 1,“02 00 00 00 “= 2,”03 00 00 00“= 3,”04 00 00 00“= 4.其他所有内容仍然是缓冲[512]变量。 But in c++, sizeof(char) == 1. The char data type usually used to represent old ASCII style text with a single byte encoding. 但在c ++中,sizeof(char)== 1. char数据类型通常用于表示具有单字节编码的旧ASCII样式文本。 You should use wchar_t instead which is perfectly fits for Unicode encodings. 您应该使用wchar_t,这非常适合Unicode编码。

Now let's take a look at 现在让我们来看看

struct Data
{
public:
    int number;
    int *array;
    char *buffer;
};

This structure will be projected on the same memory layout as described above. 该结构将被投影在与上述相同的存储器布局上。 If you're running under 32-bit environment (win32) the content of "array" pointer will be "00 00 00 00" (4 bytes for pointer) and "buffer" pointer will be "01 00 00 00". 如果您在32位环境(win32)下运行,则“数组”指针的内容将为“00 00 00 00”(指针为4个字节),“缓冲区”指针为“01 00 00 00”。

If you're running under 64-bit environment (win64) the content of "array" pointer will be "00 00 00 00 01 00 00 00" (8 bytes for pointer) and buffer pointer will be "02 00 00 00 03 00 00 00". 如果您在64位环境(win64)下运行,“数组”指针的内容将为“00 00 00 00 01 00 00 00”(指针为8个字节),缓冲区指针为“02 00 00 00 03 00” 00 00“。

These are some kind of invalid pointers which point who knows where. 这些是某种无效的指针,指出谁知道在哪里。 That's why you get Access Violation when you try to dereference them. 这就是您尝试取消引用它们时出现访问冲突的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM