In the first part of this series we saw the problems involved with using DLLs in an environment different from the one in which they were developed. In this part we will learn more about resolving some of these problems.
DLL Conventions: Issues and Solutions - Part II - Solving the problem (Page 3 of 4 )
From the first two figures above, you can clearly make out the different linker names generated by the Visual C++ Compiler and the Borland C++ Compiler. From the first figure you may see the symbols that are exported by the Borland built DLL, and they're exactly the same ones that any application developed in Borland Builder that uses this DLL would expect in the import library at link time.
But why are they different even when they're built from the same source? Yes, you guessed right! It's due to the differences in name mangling/name decoration techniques that these different compilers follow. To start with the analysis I'll first state a few facts on which our analysis will be based. The facts are:
The default calling convention for Visual C++ 6.0 is __cdecl, that is, if you don't specify or omit the calling convention (see figure 4 below) it is assumed to be __cdecl.
Fig 4: Where to look for calling convention
For instance, __declspec(dllexport) int MyFoo(void); uses __stdcall.
VC++ compiler always decorates function names that use the __stdcall calling convention. In specific cases where a module definition file has explicitly been used while building the DLL, the functions with __stdcall calling convention are not decorated or mangled. Essentially, one has less work to do if a .def file is used while building the DLL.
If you wish to provide the operability between different compilers, you can consider using a .def file to explicitly define the exported symbols. In figure 2 you can observe that the FooSTDCALL function name has been decorated to _FooSTDCALL@0. It can also be observed that the last number is usually the number of bytes that the caller have to push on the stack before calling this DLL method; but it's just an observation, and I'm not sure if it is the same in all cases. Had the DLL been built using a module definition file (.def), the exported name will appear to be FooSTDCALL without the leading underscore and the trailing @XX.
Borland C++ builder expects __cdecl function names to be decorated by prep ending an underscore.
Now that we have seen the problem in action, let's talk about the solution. The aim is to be able to use the DLL created in VC++ (with or without a .def file), which is accompanied by the header file for using that DLL in Borland C++ builder.
Essentially, based on the observations you made, you can now identify the calling convention used (by using Depends.exe and the DLL header file) and whether a .def file was used during the DLL build process (that is, the __stdcall functions are not decorated). Based on this, your approach to use the DLL in Borland Builder will vary. To proceed further, let's make a table of a single function on which we'll base our analysis.
Used Calling Convention
VC++ Linker Name
VC++ Linker Name with .def file
Expected Borland C++ Builder Linker Name
Table 1: Comparison of the generated/expected linker names