Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Runtime objects, dll boundaries

What is the best way to design a C API for dlls which deals with the problem of passing "objects" which are C runtime dependent (FILE*, pointer returned by malloc, etc...). For example, if two dlls are linked with a different version of the runtime, my understanding is that you cannot pass a FILE* from one dll to the other safely.

Is the only solution to use windows-dependent API (which are guaranteed to work across dlls) ? The C API already exists and is mature, but was designed from a unix POV, mostly (and still has to work on unix, of course).

like image 940
David Cournapeau Avatar asked Jun 27 '09 09:06

David Cournapeau


2 Answers

You asked for a C, not a C++ solution.

The usual method(s) for doing this kind of thing in C are:

  • Design the modules API to simply not require CRT objects. Get stuff passed accross in raw C types - i.e. get the consumer to load the file and simply pass you the pointer. Or, get the consumer to pass a fully qualified file name, that is opened , read, and closed, internally.

  • An approach used by other c modules, the MS cabinet SD and parts of the OpenSSL library iirc come to mind, get the consuming application to pass in pointers to functions to the initialization function. So, any API you pass a FILE* to would at some point during initialization have taken a pointer to a struct with function pointers matching the signatures of fread, fopen etc. When dealing with the external FILE*s the dll always uses the passed in functions rather than the CRT functions.

With some simple tricks like this you can make your C DLLs interface entirely independent of the hosts CRT - or in fact require the host to be written in C or C++ at all.

like image 85
Chris Becke Avatar answered Oct 22 '22 12:10

Chris Becke


Neither existing answer is correct: Given the following on Windows: you have two DLLs, each is statically linked with two different versions of the C/C++ standard libraries.

In this case, you should not pass pointers to structures created by the C/C++ standard library in one DLL to the other. The reason is that these structures may be different between the two C/C++ standard library implementations.

The other thing you should not do is free a pointer allocated by new or malloc from one DLL that was allocated in the other. The heap manger may be differently implemented as well.

Note, you can use the pointers between the DLLs - they just point to memory. It is the free that is the issue.

Now, you may find that this works, but if it does, then you are just luck. This is likely to cause you problems in the future.

One potential solution to your problem is dynamically linking to the CRT. For example,you could dynamically link to MSVCRT.DLL. That way your DLL's will always use the same CRT.

Note, I suggest that it is not a best practice to pass CRT data structures between DLLs. You might want to see if you can factor things better.

Note, I am not a Linux/Unix expert - but you will have the same issues on those OSes as well.

like image 1
Foredecker Avatar answered Oct 22 '22 13:10

Foredecker