0

I am working on a DLL project in C++ for a Delphi executable. This executable has a structure like :

size
data[]

for example :

02 00 00 00 // Size
30 31 32 33 // data[0]
34 35 36 37 // Still data[0]
31 32 33 33 // data[1]
33 33 33 33 // Still data[1]

I tried by doing a class like :

class LittleList
{
private:
    int32_t size;
    DataType* data;
}

and it gives me this :

02 00 00 00 // Size
xx xx xx xx // Pointer to data (and obviously, there are data[0] and data[1] at this address)

That is not what I want.

I can achieve my goal by using an array :

class LittleList
{
private:
    int32_t size;
    DataType data[2];
}

but then, I am forced having a fixed length, that is still not what I want.

I thought about a dirty solution :

class LittleList
{
private:
    char* data;
    // Storing size at data[0] ~ data[3]
    // and the actual data from data[4] to data[...]

}

but it would be really hard to parse, read and write.

Is there any clean solution for such a problem ?

By the way it is not a XY problem

Nox
  • 713
  • 7
  • 16
  • There is no "clean" solution. Have a look here: [Variable Sized Struct C++](https://stackoverflow.com/questions/688471/variable-sized-struct-c) – rustyx Mar 15 '21 at 14:56
  • If you read binary, you also might have to handle endianess... – Jarod42 Mar 15 '21 at 15:02
  • Both the DLL and executable are using little endian, that is not an issue. But looking at rustyx' comment, I guess I have no other choice than parsing data to char* like I was thinking. I was hoping for something simple :( – Nox Mar 15 '21 at 15:05
  • What do you mean, you don't want fixed length? Should the length be determined at run time? Or is a compile time solution possible, but you cannot type in a fixed number (templates could work in this case)? – Tobias Brösamle Mar 15 '21 at 15:16
  • The size must be determined at run time, yes – Nox Mar 15 '21 at 15:22
  • Do you want to `reinterpret_cast` the memory? Or copy is ok then `std::vector` might be used. – Jarod42 Mar 15 '21 at 15:25
  • Using reinterpret_cast is currently my solution, but do I want to use it ? I think the answer is "I don't have the choice" ! I did not understood your second sentence, but I can't use vector since it's storing datas in a pointer – Nox Mar 15 '21 at 15:47
  • Without reinterpret_cast, you might do something like: `const char data[] = "ABHello"; struct S {char a; char b; std::string s;} s{data[0], data[1], data+2};` – Jarod42 Mar 15 '21 at 16:48

1 Answers1

1

You're literally interpreting data, so there is a valid point to use a reinterpret_cast here. Don't be too afraid of Undefined Behavior - using Delphi is Undefined Behavior per se.

The easiest way seems to be a

private:
DataType& at(size_t i) { 
  assert(i<size);
  return reinterpret_cast<DataType*>(&size+1)[i];
}

which you then use as a building block.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks for the answer, this is indeed my (I was hoping temporary) solution, so I guess there is no way of doing what I wanted to achieve first : adding data right in the class, even as the latest member instead of adding data to a pointer ? – Nox Mar 15 '21 at 15:46
  • @Nox: The easiest way to understand your problem is `sizeof(LittleList)`. In C++, `sizeof` is a compile-time constant. – MSalters Mar 15 '21 at 15:48