4

I am trying to use Cython to expose a function from a static library to python. I have a myLibrary.lib and a myLibrary.dll file, but no header file. In the library, there is a function/symbol named myFunc.

So I wrote my core.pxd file:

cdef extern short myFunc(char*, short*, int*, float*, short*)

And my core.pyx file:

import numpy as np
cimport numpy as np

def get_data(char[:] path, int istart, int iend):
    cdef short err = 0
    cdef int[:] pts = np.arange(istart, iend, dtype=np.int32)
    cdef short nPts = <short>pts.shape[0]
    cdef float[:,:,:] out = np.zeros((nPts, 11, 18), dtype='f4')

    myFunc(&path[0], &nPts, &pts[0], &out[0,0,0], &err)

    return np.asarray(out)

Which I am finally building using:

from setuptools import setup, Extension
from Cython.Build import cythonize
import numpy


setup(
    ext_modules = cythonize([
        Extension('mymodule.core', ['mymodule/core.pyx'],
                  include_dirs=[numpy.get_include()],
                  libraries=['myLibrary'],
                  library_dirs=['mymodule'],
        )
    ])
)

Which I then run using:

python setup.py build_ext --inplace

However, it gives me the error:

core.obj : error LNK2001: unresolved external symbol _myFunc

It seems to be searching for the symbol _myFunc rather than myFunc. How can I prevent Cython from searching for a underscore-prefixed symbol and just use the symbol as I specified?

I am using 32-bit python 3.6, the library is 32-bit, and I have installed 32-bit versions of numpy and Cython. The library files (dll and lib) are in the same directory as the core.pyx file.

ErikRtvl
  • 326
  • 1
  • 7
  • If you library has symbol without underscore, it is 64bit. Related (but other way around): https://stackoverflow.com/a/63757694/5769463 – ead Oct 27 '20 at 20:06
  • Output from dumpbin actually says its an x86 library (Machine : 14C (x86) ). Does that mean the creators of the library have used specific compiler settings? – ErikRtvl Oct 27 '20 at 20:26
  • Your library isn’t static but a dll, as shown in the link it leads to a prefix in symbol. You need to add dllimport-declaration to your function declaration. Use dumbin to verify that the symbol is really in the lib and from the prefix + suffix you can deduce the calling convention. – ead Oct 28 '20 at 01:41
  • When specifying dllimport, I got it looking for "__imp__myFunc". In the DLL (from dumpbin), I found a "__imp_myFunc"; thus missing one underscore. So the symbols look like they're from a 64-bit library, but dumpbin says its a 32-bit library. We got the library from a third party and don't have the source code. But it turns out the library I was attempting to use was a wrapper around another (from same third party). Using the parent library, I managed to import a similar "myFunc" using __stdcall. (the symbol in the parent lib was _myFunc@20). Thanks for your help anyway! – ErikRtvl Oct 29 '20 at 08:20
  • That would be really interesting to see how they compiled this dll (or to look at their header-files). I have no idea why the name is mangled the way it is for a 32bit-build. – ead Oct 29 '20 at 09:21

0 Answers0