0

I'm trying to write some Cython code to call a vendor-supplied DLL file, but am getting some errors that I don't know how to resolve. When I run the setup file I get the following output:

PS C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\cython_attempt_2> python setup.py build_ext -i
running build_ext
cythoning FWB5180_pythonWrapper.pyx to FWB5180_pythonWrapper.c
C:\Users\Ben\AppData\Local\Programs\Python\Python39\lib\site-packages\Cython\Compiler\Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\cython_attempt_2\FWB5180_pythonWrapper.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
building 'fwb' extension
creating build
creating build\temp.win-amd64-3.9
creating build\temp.win-amd64-3.9\Release
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IC:\Users\Ben\AppData\Local\Programs\Python\Python39\include -IC:\Users\Ben\AppData\Local\Programs\Python\Python39\include -IC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\ATLMFC\include -IC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include -IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um -IC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt -IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared -IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um -IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\winrt -IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt /TcFWB5180_pythonWrapper.c /Fobuild\temp.win-amd64-3.9\Release\FWB5180_pythonWrapper.obj
FWB5180_pythonWrapper.c
C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\cython_attempt_2\FWB5180.h(15): error C2059: syntax error: 'string'
C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\cython_attempt_2\FWB5180.h(16): error C2059: syntax error: 'string'
C:\Users\Ben\Documents\UCLA\Research\Hardware\fw_bell_magnetic_field_probe\usb5100-x64\x64-dist\cython_attempt_2\FWB5180.h(17): error C2059: syntax error: 'string'
FWB5180_pythonWrapper.c(1112): warning C4013: 'openUSB5100' undefined; assuming extern returning int
error: command 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x64\\cl.exe' failed with exit code 2

The string syntax errors seem to be referring to the "C" in the extern statement. There is also an error about openUSB5100 not being defined, which I thought is in there correctly.

Anyway, here is the header file, FWB5180.h

#ifdef USB5100_EXPORTS
#define USB5100_API __declspec(dllexport)
#else
#define USB5100_API __declspec(dllimport)
#endif

extern "C" USB5100_API unsigned int openUSB5100(void);
extern "C" USB5100_API void closeUSB5100(unsigned int fwb5000ID);
extern "C" USB5100_API int scpiCommand(unsigned int usbID,char* cmd, char* result, int len);

Here is the Cython-adapted header, c_FWB5180.pxd:

cdef extern from "FWB5180.h":

    int openUSB5100()
    void closeUSB5100(int devID)
    int scpiCommand(int devID,char* cmd, char* result, int length)

Here is the python wrapper, FWB5180_pythonWrapper.pyx:

cimport c_FWB5180

def open_connection():

    devID = c_FWB5180.openUSB5100()
    print(devID)
    return devID

and here is the setup.py file (which I run with python setup.py build_ext -i:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension('fwb',
              ['FWB5180_pythonWrapper.pyx'],
              language="c",  
              libraries=['usb5100.dll','libusb0.dll'],
              library_dirs=['.'])
    ]

setup(
    name = 'FWB python wrapper',
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules
)

All of these files, along with the DLLs usb5100.dll and libusb0.dll are in the same directory. I'm using the Microsoft Visual Studio 2022 compiler. I've been able to successfully build example projects from elsewhere so I'm not so worried about the setup.

Any tips or tricks? Thanks in advance.

bpound
  • 28
  • 5
  • `extern C` has to be followed by a block in curly braces `extern C { ... }` – Barmar Jun 17 '22 at 18:59
  • @Barmar https://en.cppreference.com/w/cpp/language/language_linkage - it certainly looks like it can be applied to individual functions. – DavidW Jun 17 '22 at 20:22
  • It's apparently not allowed in C itself, so should be guarded with the preprocessor there – DavidW Jun 17 '22 at 20:23
  • @bpound - I think you'd normally link it to a .lib file rather than a dll (in your `libraries` section) – DavidW Jun 17 '22 at 20:24
  • @DavidW Hmm, I don't have a .lib file. All I have is the ```usb5100.dll``` and its dependency ```libusb0.dll``` (fyi ```libusb0.dll``` is loaded automatically by ```usb5100.dll```). I put the dll in the ```libraries``` section as inspired by [this tutorial](https://riptutorial.com/cython/example/11296/wrapping-a-dll--cplusplus-to-cython-to-python), not sure if that's actually valid or not. – bpound Jun 18 '22 at 19:55
  • I can generate a .lib file from the .dll file using an approach by vyshulga [here](https://stackoverflow.com/questions/9946322/how-to-generate-an-import-library-lib-file-from-a-dll), but I get the same errors. If I change the `language` in the setup.py to `c++`, then I don't get the string errors anymore but I get this error instead: `error LNK2001: unresolved external symbol __imp_openUSB5100`, which I can't tell if this is worse or if this is progress. I'm not super familiar with C/C++/Cython in general... – bpound Jun 18 '22 at 21:21
  • That is definitely progress (that error happens later in the compilation). Try editing the libraries line to be `libraries=['usb5100','libusb0']` (i.e. don't specify the file extension) – DavidW Jun 19 '22 at 06:43
  • Found the error - the code that I used from vyshulga to create the .lib from .dll was generating 32 bit .lib, not 64 bit .lib. Once I changed the appropriate flag, everything compiled great! The code still doesn't work because of access violations, but I guess that's a separate issue (incidentally, its the same issue I was getting with Ctypes, but hoped to solve with Cython ... ). – bpound Jun 20 '22 at 19:47

0 Answers0