Fix shared module support on Windows

Unlike Linux and OS X, when a library is loaded, all the symbols aren't
loaded into a single namespace. You must fetch the symbol by iterating over
all loaded modules.

So, we shouldn't use /FORCE:UNRESOLVED since that is not what modules do
on Windows. Instead, we now do exactly what GModule does on Windows.

Also use `void` for functions that take no arguments.
pull/1126/head
Nirbheek Chauhan 8 years ago
parent dc1f537fb3
commit f5a9b3b249
  1. 3
      mesonbuild/compilers.py
  2. 51
      test cases/common/125 shared module/module.c
  3. 92
      test cases/common/125 shared module/prog.c
  4. 2
      test cases/common/125 shared module/runtime.c

@ -1926,9 +1926,6 @@ class VisualStudioCCompiler(CCompiler):
pdbarr += ['pdb']
return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
def get_std_shared_module_link_args(self):
return ['/DLL', '/FORCE:UNRESOLVED']
class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap):
self.language = 'cpp'

@ -9,6 +9,54 @@
#endif
#endif
#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
typedef int (*fptr) (void);
/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't
* loaded into a single namespace. You must fetch the symbol by iterating over
* all loaded modules. Code for finding the function from any of the loaded
* modules is taken from gmodule.c in glib */
fptr find_any_f (const char *name) {
fptr f;
HANDLE snapshot;
MODULEENTRY32 me32;
snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
if (snapshot == (HANDLE) -1) {
printf("Could not get snapshot\n");
return 0;
}
me32.dwSize = sizeof (me32);
f = NULL;
if (Module32First (snapshot, &me32)) {
do {
if ((f = (fptr) GetProcAddress (me32.hModule, name)) != NULL)
break;
} while (Module32Next (snapshot, &me32));
}
CloseHandle (snapshot);
return f;
}
int DLL_PUBLIC func() {
fptr f;
f = find_any_f ("func_from_language_runtime");
if (f != NULL)
return f();
printf ("Could not find function\n");
return 1;
}
#else
/*
* Shared modules often have references to symbols that are not defined
* at link time, but which will be provided from deps of the executable that
@ -17,6 +65,7 @@
*/
int func_from_language_runtime();
int DLL_PUBLIC func() {
int DLL_PUBLIC func(void) {
return func_from_language_runtime();
}
#endif

@ -1,38 +1,102 @@
#include <stdio.h>
int func_from_language_runtime(void);
typedef int (*fptr) (void);
#ifdef _WIN32
// FIXME: add implementation using Winapi functions for dlopen.
int main(int argc, char **argv) {
return 0;
#include <windows.h>
wchar_t*
win32_get_last_error (void)
{
wchar_t *msg = NULL;
FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError (), 0,
(LPWSTR) &msg, 0, NULL);
return msg;
}
int
main (int argc, char **argv)
{
HINSTANCE handle;
fptr importedfunc;
int expected, actual;
int ret = 1;
handle = LoadLibraryA (argv[1]);
if (!handle) {
wchar_t *msg = win32_get_last_error ();
printf ("Could not open %s: %S\n", argv[1], msg);
goto nohandle;
}
importedfunc = (fptr) GetProcAddress (handle, "func");
if (importedfunc == NULL) {
wchar_t *msg = win32_get_last_error ();
printf ("Could not find 'func': %S\n", msg);
goto out;
}
actual = importedfunc ();
expected = func_from_language_runtime ();
if (actual != expected) {
printf ("Got %i instead of %i\n", actual, expected);
goto out;
}
ret = 0;
out:
FreeLibrary (handle);
nohandle:
return ret;
}
#else
#include<dlfcn.h>
#include<assert.h>
#include<stdio.h>
int func();
int func_from_language_runtime();
int main(int argc, char **argv) {
void *dl;
int (*importedfunc)();
int success;
fptr importedfunc;
int expected, actual;
char *error;
int ret = 1;
dlerror();
dl = dlopen(argv[1], RTLD_LAZY);
error = dlerror();
if(error) {
printf("Could not open %s: %s\n", argv[1], error);
return 1;
goto nodl;
}
importedfunc = (int (*)()) dlsym(dl, "func");
assert(importedfunc);
importedfunc = (fptr) dlsym(dl, "func");
if (importedfunc == NULL) {
printf ("Could not find 'func'\n");
goto out;
}
assert(importedfunc != func_from_language_runtime);
success = (*importedfunc)() == func_from_language_runtime();
actual = (*importedfunc)();
expected = func_from_language_runtime ();
if (actual != expected) {
printf ("Got %i instead of %i\n", actual, expected);
goto out;
}
ret = 0;
out:
dlclose(dl);
return !success;
nodl:
return ret;
}
#endif

@ -14,6 +14,6 @@
* modules.
*/
int DLL_PUBLIC func_from_language_runtime() {
int DLL_PUBLIC func_from_language_runtime(void) {
return 86;
}

Loading…
Cancel
Save