Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing data between dll boundaries in c++ Safely

Let there be a structure

struct MyDataStructure
{
    int a;
    int b;
    string c;
};

Let there be a function in the interface exposed by a dll.

class IDllInterface
{
    public:
       void getData(MyDataStructure&) = 0;
};

From a client exe which loads the dll, would the following code be safe?

...
IDllInterface* dll = DllFactory::getInterface(); // Imagine this exists
MyDataStructure data;
dll->getData(data);
...

Assume, of course, that MyDataStructure is known to both the client and the dll. Also according to what I understand, as the code is compiled separately for the dll and exe, the MyDataStructure could be different for difference compilers/compiler versions. Is my understanding correct.

If so, how can you pass data between the dll boundaries safely when working with different compilers/compiler versions.

like image 875
Abdus Khazi Avatar asked Sep 07 '25 03:09

Abdus Khazi


1 Answers

You could use a "protocol" approach. For this, you could use a memory buffer to transfer the data and both sides just have to agree on the buffer layout.

The protocol agreement could be something like:

  1. We don't use a struct, we just use a memory buffer - (pass me a pointer or whatever means toolkit allows sharing a memory buffer.
  2. We clear the buffer to 0s before setting any data in it.
  3. All ints use 4 bytes in the buffer. This means each side uses whatever int type under their compiler is 4 bytes e.g. int/long.
  4. For the particular case of two ints, the first 8 bytes has the ints and after that it's the string data.

    #define MAX_STRING_SIZE_I_NEED 128

    // 8 bytes for ints.

    #define DATA_SIZE (MAX_STRING_SIZE_I_NEED + 8)

    char xferBuf[DATA_SIZE];

So Dll sets int etc. e.g.

void GetData(void* p);

// "int" is whatever type is known to use 4 bytes

(int*) p = intA_ValueImSending;
(int*) (p + 4) = intB_ValueImSending;
strcpy((char*) (p + 8), stringBuf_ImSending);

On the receving end it's easy enough to place the buffered values in the struct:

char buf[DATA_SIZE];
void* p =(void*) buf;
theDll.GetData(p);
theStrcuctInstance.intA = *(int*) p;
theStrcuctInstance.intB = *(int*) (p + 4);
...

If you want you could even agree on the endianness of the bytes per integer and set each of the 4 bytes of each integer in the buffer - but you probably wouldn't need to go to that extent.

For more general purpose both sides could agree on "markers" in the buffer. The buffer would look like this:

<marker>
<data>
<marker>
<data>
<marker>
<data>
...

Marker: 1st byte indicates the data type, the 2nd byte indicates the length (very much like a network protocol).


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!