a paid nerd
a paid nerd

Reputation: 31512

Do I really need __declspec(dllexport) when cross-compiling a DLL with MinGW and wclang?

There are similar questions here but they don't quite answer my question:

When I cross-compile a DLL from Mac OS X using MinGW and wclang, why does my DLL work fine without using __declspec?

The MinGW DLL sample docs, and every reference I see to doing this, say to use __declspec(dllexport) before function declarations. Yet none of the code in my 9,000-line library uses it, and the DLL works great!

For example, here's a contrived example library built in the same way:

#include <stdio.h>

extern "C" {

int hello(const char* name) {
  printf("Hello, %s!\n", name);
  return 0;
}

}

Compiled with this on Mac OS X 10.10.3:

w32-clang++ test.cpp -shared -o test.dll

Produces a fine-looking DLL:

enter image description here

And my Windows application:

#include "stdafx.h"
#include <Windows.h>
#include <iostream>

typedef int(*hellofn)(const char*);

int _tmain(int argc, _TCHAR* argv[])
{
  DWORD err;

  HINSTANCE dll = LoadLibrary(L"E:\\test.dll");
  if (!dll) {
    err = GetLastError();
    std::cout << "Can't load library: " << err << std::endl;
    return 1;
  }

  hellofn hello = (hellofn)GetProcAddress(dll, "hello");
  if (!hello) {
    err = GetLastError();
    std::cout << "Could not load the function: " << err << std::endl;
    return 2;
  }

  int ret = hello("nerd");
  std::cout << "hello() returned " << ret << std::endl;

  return 0;
}

Works great:

enter image description here

Am I shooting myself in the foot somehow, or is there some magic that I'm not seeing? I'm thinking that wclang (MinGW+clang) knows to use __stdcall automatically somehow and doesn't mangle the function names?

Upvotes: 3

Views: 3027

Answers (1)

Keith Marshall
Keith Marshall

Reputation: 2034

No, you do not need __declspec(dllexport), when building a DLL with MinGW; (in fact, I frequently omit it myself). The caveat is that, if just one symbol to be included in the DLL is so decorated, then all others you wish to have exported must be likewise decorated, (unless you pass the --export-all-symbols option to the linker when you build the DLL).

If you include only undecorated symbols, then all global symbols will be exported, just as if --export-all-symbols were specified by default.

However, this has nothing whatsoever to do with __stdcall vs. __cdecl calling conventions, or name mangling; it is solely a determinant of the visibility of symbols in the DLL's export table. If you don't declare your functions to be __stdcall or __cdecl, then they will be __cdecl by default; that's no problem, provided both providing DLL and caller agree on that convention. Similarly, if both agree on any name mangling convention, (which normally means that, in the case of C++ in particular, they both used the same compiler at build time), then there will be no linking problems.

Upvotes: 4

Related Questions