1

I have an Application and DLL project that I am trying to port to a 64-bit environment. I ran into an issue with the DLL module definition that would cause linker errors such as the following when compiled with a 64-bit configuration:

2>mylib.exp : error LNK2001: unresolved external symbol _func_a@4
2>mylib.exp : error LNK2001: unresolved external symbol _func_b@4

The header definition for these functions looks like:

#ifdef MYLIB_DEF
    #define DLLEXPORT __declspec(dllexport)
#else
    #define DLLEXPORT __declspec(dllimport)
#endif

DLLEXPORT extern int variable;
DLLEXPORT int __stdcall func_a(int value);
DLLEXPORT int __stdcall func_b(int value);

And in the C source file, it starts with this:

#define MYLIB_DEF
#include "mylib.h"

DLLEXPORT int variable;

DLLEXPORT int __stdcall func_a(int value)
{
...

Now, for the trouble part. We have something like this for the module definition file:

LIBRARY mylib.dll
EXPORTS
variable DATA
_func_a@4
func_a@4=_func_a@4
func_a=_func_a@4
_func_b@4
func_b@4=_func_a@4
func_b=_func_a@4

This triggers the aforementioned errors. I understand that MSVC decorates functions when compiled with __stdcall and 64-bit builds don't use/support __stdcall so there are no decorations. I was able to create an alternate definition file that seems to work like this:

LIBRARY mylib.dll
EXPORTS
variable DATA
func_a
func_b

But, as this file was last touched 10 years ago, I don't know if I understand all the implications or reasoning behind the use of this file. Would something like that file be adequate for 64-bit builds. While our app is the primary user of our DLL, we do have others that interface to the DLL directly so I do not want to break any compatibility, however, we have zero users of a 64-bit version at the moment.

Do we need the definition file at all if we are using __declspec(dllexport) everywhere and not using ordinal exports?

Should we just drop it for 64-bit builds or does it provide any value?

Does dropping it from 32-bit builds as unneeded noise risk breaking any external users? From local testing, it does not seem to be required, but I am doing a full rebuild of the app and DLL.

Why does every function need two additional aliases? Is this standard practice for 32-bit builds? Is there a 64-bit equivalent we should be doing?

I've looked over Microsoft's documentation on the topic, but it says nothing about 64-bit builds versus 32-bit builds:

https://learn.microsoft.com/en-us/cpp/build/reference/exports?view=msvc-170

penguin359
  • 1,289
  • 13
  • 26
  • Have you tried dropping `__stdcall` entirely? You might try to compile conditionally like e.g. [here](https://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c) or [here](https://stackoverflow.com/questions/163058/how-can-i-detect-if-im-compiling-for-a-64bits-architecture-in-c), which might look like `#if BUILD32 #define CALLCONV __stdcall #else #define CALLCONV`. – Aconcagua Jan 05 '23 at 09:42
  • Is the DLL used *only* by your applications? If so, then you can drop the .def file (as you seem to have discovered). If the DLL is also for public use/consumption, then you need to be sure that other clients aren't using the ordinal-style exports. – Adrian Mole Jan 05 '23 at 10:29
  • ... or you can conditionally (for 64-bit builds) explicitly specify a decorated export name, like in [this answer](https://stackoverflow.com/a/2805560/10871073). – Adrian Mole Jan 05 '23 at 10:39
  • @Aconcagua My understanding is that dropping it from 32-bit builds would break existing users of the DLL and that it's completely ignored in 64-bit builds so it shouldn't affect anything. – penguin359 Jan 05 '23 at 19:54
  • @AdrianMole We do have external users of the 32-bit DLL. However, as we don't have the extra @ followed by a number with a space in front of it to separate it from the symbol, I don't think it supports ordinal linking from my understanding. If that's the case, then existing users would only be linking based on names. However, I don't understand all the details fully so I want to make sure it won't change the linkage. – penguin359 Jan 05 '23 at 19:56
  • @penguin359 I recall vaguely having had problems in this respect once – not all compilers might ignore it (I *think* GCC, for instance, doesn't), so don't know how MSVC behaves in this respect. Did not mean to drop it for 32-it builds anyway, thus the conditional definition of __stdcall for 32-bit build and empty for 64-bit. – Aconcagua Jan 06 '23 at 23:43

0 Answers0