Is it possible to make a string be a specific size when defining a structure?

I am collecting data between a C # and C ++ application. In a C # application, I force the string size to be some size (say 256 bytes). I would like to read the same amount in C ++ (I will recreate the structures with reinterpret_cast) so that the data remains in the format as it was in the C # application. Unfortunately, I'm pretty rusty with C ++, and I'm not sure how to force the size of a string in a C ++ structure.

As requested, example. I have a C # structure that looks like this:

[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; } 

I collect several files (along with other data) into a data file. Then the C ++ file reads this file, and I will parse it back into a C ++ struct with the same structure. My first attempt at this structure looked like this:

 struct DataLocater { std::string filename; int sizeOfData; int startLocation; int encrypted; }; 

But the compiler does not know that I want std :: string to be 256 bytes.

edit: add a complete header file, e.g.

 #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; }; }; 
+4
source share
4 answers

In general, you are mistaken here. Mixing non-data with only C ++ and PInvoke types will lead to a lot of pain. Types such as std :: string should not be used in this script because the marshaller cannot correctly create them at run time.

Instead, you need to use more primitive types. In this particular scenario, based on a managed signature, the corresponding C structure is as follows

 struct DataLocater { char filename[256]; int sizeOfData; int startLocation; int encrypted; }; 
+6
source

Is this what you are looking for?

 struct DataLocater { char filename[256]; int sizeOfData; int startLocation; int encrypted; }; 

edit: consider that you DO NOT NEED any line to have a certain size, you could declare the file name as char * , and with C # size you would use the line without restrictions. Therefore, you should use as much memory as necessary (and possibly use more than you originally estimated, avoiding buffer overflow errors).

+6
source

You cannot massage C # arrays directly in std::string . The string class has a whole bunch of other things in its memory space besides raw character data: a vtable pointer, a length specifier, and probably a lot of other things.

You need to specify the file name parameter as wchar [256], and then convert wchar[256] to std::string .

+2
source

A std :: string is not a fixed length and usually does not save its data in the allocated space, but on the heap. You want an array of fixed length characters or bytes, depending on the character set structure.

ByValTStr MSDN examples to use ByValTStr gives the following three:

 // C struct StringInfoA { char f2[256]; }; struct StringInfoW { WCHAR f2[256]; }; struct StringInfoT { TCHAR f2[256]; }; 

Which corresponds

 // 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; } 
+1
source

All Articles