简体   繁体   中英

Wrapping C/C++ Library with SWIG

I've got a project that I'm working on that requires the use of a Topaz Signature Capture pad. Our product currently uses the ActiveX control provided by Topaz for collecting signatures on a website, but we're trying to move to a desktop application powered by Python. Python will allow us to branch out into multiple OS's without too much extra work.

Topaz provides a 'C' library ( http://www.topazsystems.com/sigpluslibrary.html ) for interfacing with their devices. I believe I've determined that it is actually C++ (uses classes and other C++ constructs). I've attempted to create a wrapper for Python using SWIG and Cython, but I have not had a whole lot of luck.

My directory structure for SWIG is this:

  • SigSwig
    • Includes (contains all of the headers from Topaz Shared C Library)
    • setup.py
    • SigLib.i
    • Signature.i
    • etc...

Setup.py

# setup.py
import distutils
from distutils.core import setup, Extension

module = Extension(
                        "_SigLib", 
                        ["SigLib.i"],
                        swig_opts=['-c++'],
                        language='c++',
                        library_dirs=['c:\Python27'],
                        libraries=["SigLib", "hid", "LibJpeg", "libtiff", "WINTAB32", "WNTAB32X", "zlib"],
                        extra_options=["SigLib.lib", "hid.lib", "LibJpeg.lib", "libtiff.lib", "WINTAB32.LIB", "WNTAB32X.LIB", "zlib.lib"]
                    )

setup(
      name = "Signature Capture",
      version = "1.0",
      ext_modules = [module]
)

SigLib.i

%module SigLib
%{
#define SIGAPI 
#include "Include\SigLib.h"
%}

%include TabletParameters.i
%include TabletInterface.i
%include LCDInterface.i
%include Signature.i

Signature.i

%module Signature
%include "Include\Signature.h"

I'm having a hard time following the SWIG examples, but from what I can tell this should be okay. SigLib.i loads in the main header (SigLib.h), which includes the declarations for SIGAPI and all of the main include files. It doesn't include Signature.h (or any of the other headers in the other interface files) since it doesn't follow all headers. Then it loads in additional interface files. Signature.i, and all of the other interface files just include a reference to the header to parse.

I've tried a few different ways and this seems to have been the best so far. However, when I execute setup.py, I get these errors:

SigLib_wrap.cpp(3417) : error C2065: 'temp' : undeclared identifier
SigLib_wrap.cpp(3418) : error C2065: 'temp' : undeclared identifier
SigLib_wrap.cpp(3418) : error C2059: syntax error : '*'
SigLib_wrap.cpp(3419) : error C2513: 'TabletParameters' : no variable declared before '='
SigLib_wrap.cpp(3419) : error C2065: 'temp' : undeclared identifier
SigLib_wrap.cpp(3420) : error C2065: 'temp' : undeclared identifier
SigLib_wrap.cpp(3420) : error C2541: 'delete' : cannot delete objects that are not pointers
SigLib_wrap.cpp(3432) : error C2275: 'TabletParameters' : illegal use of this type as an expression c:\users\kevin\downloads\sigpython\include\TabletParameters.h(18) : see declaration of 'TabletParameters'

Looking at the generated code, most of the errors contain SIGAPI, like this:

SIGAPI * temp;

SIGAPI appears to be a #define the occurs in the SigLib.h file and is used in class definitions like:

class SIGAPI Signature

SigLib.h definition:

#ifdef  SIGLIBDLL
#define SIGAPI  __declspec( dllexport ) 
#else
#define SIGAPI
#endif

I've tried hours of Googling trying to find a solution to this, but I haven't had any luck. I haven't been able to find anything in the SWIG documentation on it, but I'm honestly not really sure what to look for.

Edit:

Made the change Giorgos suggested in addition to loading in extra headers. It appears to generate the entire wrap file now with everything needed, but gets errors linking to libraries.

SigLib.i

%module SigLib
%{
    #include "Include\SigLib.h"
%}


%include <windows.i>
%include "Include\SigLib.h"
%include "Include\SigPoint.h"
%include "Include\SigStroke.h"
%include "Include\TabletParameters.h"
%include "Include\CircularBuffer.h"
%include "Include\SerialIoIF.h"
%include "Include\HidIoIF.h"
%include "Include\UsbIoIF.h"
%include "Include\SocketIoIF.h"
%include "Include\NewSocketIoIF.h"
%include "Include\SimIoIF.h"
%include "Include\ProcessSerialData.h"
%include "Include\CaptureSig.h"
%include "Include\TabletPoint.h"
%include "Include\PointBuffer.h"
%include "Include\TabletInterface.h"
%include "Include\TabletSampleList.h"
%include "Include\SigWindowType.h"
%include "Include\SigFile.h"
%include "Include\md5.h"
%include "Include\Utilities.h"
%include "Include\HotSpot.h"
%include "Include\HotSpotList.h"
%include "Include\BitmapCharacter.h"
%include "Include\CharacterMap.h"
%include "Include\TiffImage.h"
%include "Include\LCDGraphicBitmap.h"
%include "Include\LCDInterface.h"

I did that and changed up how I loaded everything in. Now it appears to be compiling, but I'm getting many linking errors like these:

SigLib_wrap.obj : error LNK2019: unresolved external symbol "public: int __thiscall TabletInterface::PointsInPointBuffer(void)" (?PointsInPointBuffer@TabletInterface@@QAEHXZ) referenced in function __wrap_TabletInterface_PointsInPointBuffer

SigLib_wrap.obj : error LNK2019: unresolved external symbol "public: void __thiscall TabletInterface::InitProcessInputData(void)" (?InitProcessInputData@TabletInterface@@QAEXXZ) referenced in function __wrap_TabletInterface_InitProcessInputData

SigLib_wrap.obj : error LNK2019: unresolved external symbol "public: void __thiscall TabletInterface::CloseProcessInputData(void)" (?CloseProcessInputData@TabletInterface@@QAEXXZ) referenced in function __wrap_TabletInterface_CloseProcessInputData

I need to link against SigLib.lib and a few other lib files, but I'm not sure how to do that from the setup.py file I have and if that will even work for Python.

From paragraph 3.4 of the SWIG documentation:

A common problem when using SWIG on Windows are the Microsoft function calling conventions which are not in the C++ standard. SWIG parses ISO C/C++ so cannot deal with proprietary conventions such as __declspec(dllimport), __stdcall etc. There is a Windows interface file, windows.i, to deal with these calling conventions though. The file also contains typemaps for handling commonly used Windows specific types such as __int64, BOOL, DWORD etc. Include it like you would any other interface file, for example:

 %include <windows.i> __declspec(dllexport) ULONG __stdcall foo(DWORD, __int32); 

Adding %include <windows.i> before any windows specific declarations will probably sovle your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM