drhagen
drhagen

Reputation: 9592

Equivalent to dlopen(None) in Windows

I am using Python CFFI and want to open a library where I can call free on some data I get back. In Linux and Mac, I put free in the cdefs and load a base C library with dlopen(None).

from cffi import FFI

header = """
    typedef struct {
      int32_t*     members;
    } container_t;

    void free(void *ptr);
"""

cdefs = FFI()
cdefs.cdef(header)
cdefs.set_source("_main", "")  # So that the header can be `include`d externally
lib = cdefs.dlopen(None)


def free_members(container) -> None:
    lib.free(container.members)

This fails on Windows with the well-documented error:

OSError: dlopen(None) cannot work on Windows for Python 3 (see http://bugs.python.org/issue23606)

What gives the equivalent behavior on Windows? I just want free, which should be available on any old DLL anywhere.

Upvotes: 2

Views: 234

Answers (1)

Armin Rigo
Armin Rigo

Reputation: 12990

Try to use the API approach with ffi_builder.compile(). This lets you write portable C code like

ffi_builder.cdef(""" void free(void *); """)
ffi_builder.set_source("_main", "")
ffi_builder.compile()

and then you can use

from _main import lib, ffi
lib.free(p)

Trying to get the correct free() function is a complete mess on Windows, because it is not standard. There are a number of libraries (and multiple versions of them) that each provide malloc() and free(), and of course if you mix the malloc() from one library with the free() from another, then everything explodes. The solution I describe above should work if compile() happens to use the same compiler (and version!) as the one that was used to make your library. In general, that's why it's a poor design on Windows to say "this function returns a pointer and you have to call free() yourself".

Upvotes: 5

Related Questions