Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to force a string to be a specific size when defining a struct?

I am marshalling data between a C# and C++ application. In the C# application, I force the size of a string to be some size (say, 256 bytes). I would like to read in that exact same amount in C++ (I will be recreating the structs with reinterpret_cast) so that the data will remain formatted as it was in the C# application. Unfortunately, I'm pretty rusty with C++ and I'm not sure how to force a string's size in a struct in C++.

As requested, an example. I have a struct in C# 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;
        }

Which I am marshalling several of (along with other data) to a data file. The C++ file is then reading this file in and I will be parsing it back into struct in C++ with the same structure. My first attempt at this struct looked like:

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

But there is no way for the compiler to know that I want that std::string to be 256 bytes.

edit: adding full header file for example.

#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;
    };
};
like image 506
Chris Avatar asked Dec 08 '22 06:12

Chris


2 Answers

In general you're taking the wrong approach here. Mixing non-data only C++ types and PInvoke will lead you to a lot of pain. Types like std::string should not be used in this scenario because the marshaller cannot correctly create them at runtime.

Instead you need to use more primitive types. In this particular scenario, based on the managed signature, the appropriate C struct is the following

struct DataLocater
{
    char filename[256];
    int sizeOfData;
    int startLocation;
    int encrypted;
};
like image 164
JaredPar Avatar answered Jan 04 '23 23:01

JaredPar


Is this what you are looking for?

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

edit: Consider that you don't NEED to force either string to be of a certain size, you could declare filename as char * and on the C# size you'd use a string with no restrictions. This way you'd only use as much memory as needed (and possibly use more than you initially estimated, avoiding buffer overrun errors).

like image 26
Blindy Avatar answered Jan 05 '23 00:01

Blindy