Skip to content

Commit e59ec8f

Browse files
authored
Win32: pass the flags from dlopen() to LoadLibraryEx() (#65)
* Win32: pass the flags from dlopen() to LoadLibraryEx() Includes a default handling if flags==0, similar to the one in ctypes. * Fix a compiler warning * Document the new behavior of ffi.dlopen()
1 parent 0619e5e commit e59ec8f

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

doc/source/cdef.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,14 @@ Useful if you have special needs (e.g. you need the GNU extension
381381
automatically if the FFI object is garbage-collected (but you can still
382382
call ``ffi.dlclose()`` explicitly if needed).
383383

384+
*New in version 1.17:* on Windows, ``ffi.dlopen(filename, flags=0)`` now
385+
passes the flags to ``LoadLibraryEx()``. Moreover, if you use the
386+
default value of 0 but ``filename`` contains a slash or backslash
387+
character, it will instead use
388+
``LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR``.
389+
This ensures that dependent DLLs from the same path are also found.
390+
It is what ctypes does too.
391+
384392

385393
.. _set_source:
386394

src/c/_cffi_backend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4570,7 +4570,7 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
45704570
if (sz1 < 0)
45714571
return NULL;
45724572
w1[sz1] = 0;
4573-
handle = dlopenW(w1);
4573+
handle = dlopenWinW(w1, flags);
45744574
goto got_handle;
45754575
}
45764576
PyErr_Clear();

src/c/misc_win32.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,30 @@ static PyObject *b_getwinerror(PyObject *self, PyObject *args, PyObject *kwds)
191191
#define RTLD_GLOBAL 0
192192
#define RTLD_LOCAL 0
193193

194-
static void *dlopen(const char *filename, int flag)
194+
static void *dlopen(const char *filename, int flags)
195195
{
196-
return (void *)LoadLibraryA(filename);
196+
if (flags == 0) {
197+
for (const char *p = filename; *p != 0; p++)
198+
if (*p == '\\' || *p == '/') {
199+
flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
200+
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
201+
break;
202+
}
203+
}
204+
return (void *)LoadLibraryExA(filename, NULL, flags);
197205
}
198206

199-
static void *dlopenW(const wchar_t *filename)
207+
static void *dlopenWinW(const wchar_t *filename, int flags)
200208
{
201-
return (void *)LoadLibraryW(filename);
209+
if (flags == 0) {
210+
for (const wchar_t *p = filename; *p != 0; p++)
211+
if (*p == '\\' || *p == '/') {
212+
flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
213+
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
214+
break;
215+
}
216+
}
217+
return (void *)LoadLibraryExW(filename, NULL, flags);
202218
}
203219

204220
static void *dlsym(void *handle, const char *symbol)

0 commit comments

Comments
 (0)