Search code examples
cythonloadlibrarypyd

Issue loading cython cdef functions in a .pyd using LoadLibrary


I'm trying to dynamically load a cythonized .pyd in c++. In a linux machine a .so file is created.

Using a .so I can do the following:

plugin = dlopen("foo.so", RTLD_LAZY);
init = dlsym(plugin, "PyInit_foo); // This works!
cfunc = dlsym(plugin, "foo_func"); // This works!
dlclose(plguin);

Which works great!


However, in windows I want to do the following:

plugin = LoadLibraryA("foo.pyd");
init = GetProcAddress(plugin, "PyInit_foo"); // This works!
cfunc = GetProcAddress(plugin, "foo_func"); // This doesn't work..
freeLibrary(plugin);

This is my issue! foo_func doesn't exist in the .pyd even though it's in the .so

Both are made using the same setup.py:

from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy

setup(
        name= "foo",
        ext_modules = cythonize("foo.pyx"),
        include_dirs = [numpy.get_include()]
        )

And an example foo.pyx

cdef public void foo_func(int i) with gil:
    print(i)

So next I looked into the .pyd using dumpbin /exports foo.pyd. And the only function is PyInit_foo. So it seems that .pyd is different than a .so. When using objdump -T foo.so in linux all the functions are there!

Do I need to cythonize the file differently for windows? What else could be different here?


Solution

  • I needed to force cython to export the functions as visible. To do this, add the export_symbols = [] to force the functions to be visible in windows.

    setup(
            name= "foo",
            ext_modules = cythonize(Extension('foo',sources= 
            ["foo.pyx"],export_symbols=['foo_func'])),
            include_dirs = [numpy.get_include()]
            )