Hi There,
I figured I would start a new thread to address my new problem mentioned in the previous thread I started.
I am trying to use Cython to wrap a C++ library (for the Saleae logic analyzer) on Windows (.dll + .lib). I have finally got it to sort of work using the MSVC compiler instead of MinGW. It looks like I can wrap a simple function in the external library that takes no arguments. However, now I am trying to register a callback, and I am getting an unresolved symbol error when linking.
The .h file provided by Saleae contains the following:
.
.
typedef signed long long int S64;
.
.
#if defined(API_RELEASE)
#if defined(WIN32)
#define SALEAE_DEVICE_API __declspec(dllexport)
#else
#define SALEAE_DEVICE_API __attribute__ ((visibility("default")))
#define __stdcall
#endif
#else
#define SALEAE_DEVICE_API
#ifndef WIN32
#define __stdcall
#endif
#endif
class SALEAE_DEVICE_API DevicesManagerInterface
{
public:
static void BeginConnect(); //Call this function to start connecting to Logic. Wait for a OnConnect callback before talking with Logic.
static void RegisterOnConnect( void (__stdcall *callback)( U64 device_id, GenericInterface* device_interface, void* user_data ), void* user_data = NULL ); //Callback registration
static void RegisterOnDisconnect( void (__stdcall *callback)( U64 device_id, void* user_data ), void* user_data = NULL ); //Callback registration
static void DeleteU8ArrayPtr( U8* array_ptr ); //use this to delete memory provided to you from the SDK. i.e. In Logic's OnReadData callback
private:
static bool mInitVar;
static bool InitFunc();
};
I can successfully wrap and call the "BeginConnect" method, but now I am struggling with the "RegisterOnConnect" method. Here is my current .pyx file:
cdef extern from "SaleaeDeviceApi.h":
cdef cppclass GenericInterface
ctypedef unsigned long long int U64
cdef extern from "SaleaeDeviceApi.h" namespace "DevicesManagerInterface":
cdef void BeginConnect()
cdef void RegisterOnConnect( void (__stdcall *callback)( U64 device_id, GenericInterface* device_interface, void* user_data ), void* user_data = NULL )
cdef public void __stdcall OnConnect(U64 device_id, GenericInterface* device_interface, void* user_data ):
print "Yo!"
cdef test():
RegisterOnConnect(&OnConnect)
BeginConnect()
def run_test():
test()
This compiles fine, but fails linking with the following error:
C:\_work\scripts\python\saleae>c:\python27\python setup.py build_ext --inplace
running build_ext
cythoning test.pyx to test.cpp
building 'SaleaeDeviceApi' extension
C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -IC:\_work\scripts\python\saleae -Ic:\python27\include -Ic:\python27\PC /Tptest.cpp /Fobuild\temp.win32-2.7\Release\test.obj
test.cpp
c:\_work\scripts\python\saleae\test.cpp(467) : warning C4700: uninitialized local variable '__pyx_v_ptr' used
C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:C:\_work\scripts\python\saleae /LIBPATH:c:\python27\libs /LIBPATH:c:\python27\PCbuild SaleaeDevice.lib /EXPORT:initSaleaeDeviceApi build\temp.win32-2.7\Release\test.obj /OUT:C:\_work\scripts\python\saleae\SaleaeDeviceApi.pyd /IMPLIB:build\temp.win32-2.7\Release\SaleaeDeviceApi.lib /MANIFESTFILE:build\temp.win32-2.7\Release\SaleaeDeviceApi.pyd.manifest
Creating library build\temp.win32-2.7\Release\SaleaeDeviceApi.lib and object
build\temp.win32-2.7\Release\SaleaeDeviceApi.exp
test.obj : error LNK2019: unresolved external symbol "public: static void __cdecl DevicesManagerInterface::RegisterOnConnect(void (__cdecl*)(unsigned __int64,class GenericInterface *,void *),void *)" (?RegisterOnConnect@DevicesManagerInterface@@SAXP6AX_KPAVGenericInterface@@PAX@Z2@Z) referenced in function "struct _object * __cdecl __pyx_f_15SaleaeDeviceApi_test(void)" (?__pyx_f_15SaleaeDeviceApi_test@@YAPAU_object@@XZ)
C:\_work\scripts\python\saleae\SaleaeDeviceApi.pyd : fatal error LNK1120: 1 unresolved externals
error: command '"C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\link.exe"'
failed with exit status 1120
I don't quite understand why there is an unresolved symbol. I originally thought that it was Cython making my function __cdecl instead of __stdcall, but if I check the generated C code, my functions were generated properly with __stdcall in front. Does anyone have any ideas as to what my be going wrong here? It is obviously finding and linking with the SaleaeDevice library properly because it looks like the function DevicesManagerInterface::BeginConnect() wraps just fine.
I am using Python 2.7 on Windows XP, 32-bit.
Thanks in advance,
Mark.