I am trying to write a Cython interface to a (Photron) camera driver DLL. This library offers an SDK with header files and Windows libs for 32 and 64 bits. I already successfully compiled a C++ example using this library in VisualStudio. The Cython compilation on the other hand fails at linking.
The custom Cython code consists of a typedefs.pxd file containing the types, a photron.pxd file containing the constants and function declarations from the SDK header and a wrapper cdef class in a camera.pyx file.
In the setup.py file, in the Extension (imported from setuptools) section I have included the sections below:
include_dirs=[s.path.abspath(os.path.normpath('./include'))],
libraries=[os.path.join(os.path.abspath(os.curdir), 'Lib', '64bit(x64)', 'PDCLIB')],
library_dirs=[os.path.abspath(os.path.normpath('./Lib/64bit(x64)'))],
I also tried the flags from the command line of the successful C++ compilation. To allow the initial cythonization step to work (generating the cpp file) I also had to add this to the header of the SDK:
#include <windows.h>
Below is a relevant excerpt from the pxd file:
from typedefs cimport ulong, uint
cdef extern from "PDCFUNC.h":
ulong PDC_CloseDevice(ulong nDeviceNo, ulong *pErrorCode)
When I try to compile the code, I get the cpp file but when the linking is attempted, I get a series of lines like the following for each of the functions I declare in the pxd file:
camera.obj : error LNK2001: unresolved external symbol "unsigned long __cdecl PDC_CloseDevice(unsigned long,unsigned long *)" (?PDC_CloseDevice@@YAKKPEAK@Z)
I suppose this is because the linker tries to find a __cdecl function in the specified headers although the functions are declared this way in the header file:
unsigned long WINAPI PDC_CloseDevice(unsigned long nDeviceNo, unsigned long *pErrorCode);
Since the Cython documentation clearly states that calling conventions are supported, I thus tried to:
__pyx_v_ret = PDC_CloseDevice(__pyx_v_self->device_nb, (&__pyx_v_error_code));
The __cdecl warnings might also be a red herring but I have no other lead and I am normally not compiling under Windows so I have a limited knowledge of the tools.
After trying everything else, including all the options from the visual studio project that compiled correctly, I restarted with a minimal example with only the following in the pxd file
cdef extern from "PDCLIB.h"
ulong __stdcall PDC_Init(ulong *pErrorCode)
ulong __stdcall PDC_CloseDevice(ulong nDeviceNo, ulong *pErrorCode)
and a simpler pyx file with the same name apart from the extension.
from pyphotron_pdclib cimport *
from typedefs cimport ulong, uint
cpdef init_pdc_lib():
cdef ulong error_code = 0
success = PDC_Init(&error_code)
assert success != 0
cpdef close_cam(ulong dev_num):
cdef ulong error_code = 0
success = PDC_CloseDevice(dev_num, &error_code)
assert success != 0
The main differences I see in the compilation is that
The compilations and linking options in the setup file are as follows:
extra_compile_args=['/Gz', '/fp:precise', '/Zc:wchar_t', '/Zc:forScope', '/Zc:inline'],
extra_link_args=['/DEBUG', '/MACHINE:X64'],