我在C#和C ++应用程序之间编组数据。在C#应用程序中,我强制将字符串的大小设置为某个大小(例如,256字节)。我想在C ++中读取完全相同的数量(我将使用reinterpret_cast重新创建结构),以便数据保持格式化,就像在C#应用程序中一样。不幸的是,我对C ++很生疏,我不知道如何在C ++中强制使用字符串的大小。
根据要求,举个例子。我在C#中有一个结构,如下所示:
[StructLayout(LayoutKind.Sequential)]
public struct DataLocater
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string filename;
[MarshalAs(UnmanagedType.I4)]
public Int32 sizeOfData;
public Int32 startLocation;
public Int32 encrypted;
}
我正在将数个(连同其他数据)编组到数据文件中。然后C ++文件读取此文件,我将使用相同的结构将其解析回C ++中的struct。我对这个结构的第一次尝试看起来像:
struct DataLocater
{
std::string filename;
int sizeOfData;
int startLocation;
int encrypted;
};
但编译器无法知道我希望std :: string为256字节。
编辑:例如添加完整的头文件。
#pragma once
#include "CoreArea/Singleton.h"
class FileReader : public Singleton<FileReader>
{
friend class Singleton<FileReader>;
public:
void* GetFileData(std::wstring fileName, int &size);
private:
FileReader();
~FileReader();
struct Header
{
std::string somestring;
int numOfFiles;
};
struct DataLocater
{
char[256] filename;
int sizeOfData;
int startLocation;
int encrypted;
};
};
答案 0 :(得分:6)
这是你在找什么?
struct DataLocater
{
char filename[256];
int sizeOfData;
int startLocation;
int encrypted;
};
编辑:考虑到你不需要强制任何一个字符串具有一定的大小,你可以将文件名声明为char *
,而在C#大小上你要使用一个没有限制的字符串。这样你只需要使用尽可能多的内存(并且可能使用比你最初估计的更多,避免缓冲区溢出错误)。
答案 1 :(得分:6)
一般来说,你在这里采取了错误的做法。混合非数据只有C ++类型和PInvoke将带来很多痛苦。不应在此场景中使用类似std :: string的类型,因为编组器无法在运行时正确创建它们。
相反,您需要使用更原始的类型。在此特定方案中,基于托管签名,适当的C结构如下
struct DataLocater
{
char filename[256];
int sizeOfData;
int startLocation;
int encrypted;
};
答案 2 :(得分:2)
您无法直接将C#数组编组到std::string
中。除了原始字符数据之外,字符串类在其内存空间中还有一大堆其他东西:vtable指针,长度说明符,也可能是其他一些东西。
您需要将filename参数指定为wchar [256],然后将wchar[256]
转换为std::string
。
答案 3 :(得分:1)
std :: string的长度不固定,通常不会将其数据存储在已分配的空间中,而是存储在堆中。您需要一个固定长度的字符或字节数组,具体取决于结构的字符集。
修改MSDN上ByValTStr
使用的示例会给出这三个:
// C
struct StringInfoA {
char f2[256];
};
struct StringInfoW {
WCHAR f2[256];
};
struct StringInfoT {
TCHAR f2[256];
};
对应
// C#
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct StringInfoA {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
struct StringInfoW {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct StringInfoT {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
}