简体   繁体   English

使用Windows .dll中的SWIG包装函数

[英]Using SWIG wrapped functions from Windows .dll

I'm having a problem using functions from a .dll shared library that is exported with SWIG interface. 我在使用通过SWIG接口导出的.dll共享库中的函数时遇到问题。

Version Info 版本信息

Python: 2.6.4 Python:2.6.4

Swig: 2.0.4 Swig:2.0.4

The big picture is: I have some code developed under Linux using C++ and wrapped using SWIG. 总体情况是:我在Linux下使用C ++开发了一些代码,并使用SWIG进行封装。 I compiled the C++ source into a .so object under Linux and use the .so library in Python. 我将C ++源代码编译成Linux下的.so对象,并在Python中使用.so库。

Now, I need to migrate all these functions to windows and the equivalent for .so in Windows is a .dll . 现在,我需要将所有这些函数迁移到Windows,而Windows中的.so的等效函数是.dll So, I planned to compile all the C++ source codes into a .dll and access them through Python. 因此,我计划将所有C ++源代码编译成.dll并通过Python访问它们。

So the normal procedure would be: have the C++ source -> wrap them using SWIG -> compile into .dll -> access through Python. 所以正常的程序是:拥有C ++源代码 - >使用SWIG封装它们 - >编译成.dll - >通过Python访问。

There is a huge .cxx source file generated using SWIG which contains all the functions I developed. 使用SWIG生成了一个巨大的.cxx源文件,其中包含我开发的所有功能。 The task now is to compile this SWIG generated file into a .dll so that I can use all the functions later. 现在的任务是将这个SWIG生成的文件编译成.dll以便以后可以使用所有函数。 However, the .cxx file uses some weird way of wrapping all my functions and I have no clue how to use them. 但是,.cxx文件使用了一些奇怪的方式来包装我的所有函数,我不知道如何使用它们。

The functions are wrapped as follows. 功能包括如下。 Ssay I have a C++ class called sdrts_reverse_burst_ff , after wrapping, the class becomes a function in the .cxx file and is defined like this: Ssay我有一个名为sdrts_reverse_burst_ff的C ++类,在包装之后,该类成为.cxx文件中的一个函数,并且定义如下:

SWIGINTERN PyObject *_wrap_sdrts_reverse_burst_ff_sptr___deref__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {

PyObject *resultobj = 0;

boost::shared_ptr< sdrts_reverse_burst_ff > *arg1 = (boost::shared_ptr< sdrts_reverse_burst_ff > *) 0 ;

  void *argp1 = 0 ;

  int res1 = 0 ;

  PyObject * obj0 = 0 ;

  sdrts_reverse_burst_ff *result = 0 ;



  if(!PyArg_UnpackTuple(args,(char *)"sdrts_reverse_burst_ff_sptr___deref__",1,1,&obj0)) SWIG_fail;

  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_boost__shared_ptrT_sdrts_reverse_burst_ff_t, 0 |  0 );

  if (!SWIG_IsOK(res1)) {

    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "sdrts_reverse_burst_ff_sptr___deref__" "', argument " "1"" of type '" "boost::shared_ptr< sdrts_reverse_burst_ff > *""'"); 

  }

  arg1 = reinterpret_cast< boost::shared_ptr< sdrts_reverse_burst_ff > * >(argp1);

  result = (sdrts_reverse_burst_ff *)(arg1)->operator ->();

  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_sdrts_reverse_burst_ff, 0 |  0 );

  return resultobj;

fail:

  return NULL;

}

That's not all: near the end of this .cxx file there is a huge array which contains all the class functions like this: 这不是全部:接近这个.cxx文件的末尾有一个巨大的数组,其中包含所有类函数,如下所示:

PyMethodDef SwigMethods[] = {

  { (char *)"sdrts_reverse_burst_ff_sptr___deref__", _wrap_sdrts_reverse_burst_ff_sptr___deref__, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr___deref__(sdrts_reverse_burst_ff_sptr self)"},

  { (char *)"delete_sdrts_reverse_burst_ff_sptr", _wrap_delete_sdrts_reverse_burst_ff_sptr, METH_VARARGS, (char *)"delete_sdrts_reverse_burst_ff_sptr(sdrts_reverse_burst_ff_sptr self)"},

  { (char *)"sdrts_reverse_burst_ff_sptr_set_reverse_burst", _wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_set_reverse_burst(sdrts_reverse_burst_ff_sptr self, int samples) -> int"},

  { (char *)"sdrts_reverse_burst_ff_sptr_enable_reverse_burst", _wrap_sdrts_reverse_burst_ff_sptr_enable_reverse_burst, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_enable_reverse_burst(sdrts_reverse_burst_ff_sptr self) -> int"},

  { (char *)"sdrts_reverse_burst_ff_sptr_reset", _wrap_sdrts_reverse_burst_ff_sptr_reset, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_reset(sdrts_reverse_burst_ff_sptr self) -> int"},

  { (char *)"sdrts_reverse_burst_ff_sptr_history", _wrap_sdrts_reverse_burst_ff_sptr_history, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_history(sdrts_reverse_burst_ff_sptr self) -> unsigned int"},

  { (char *)"sdrts_reverse_burst_ff_sptr_output_multiple", _wrap_sdrts_reverse_burst_ff_sptr_output_multiple, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_output_multiple(sdrts_reverse_burst_ff_sptr self) -> int"},

  { (char *)"sdrts_reverse_burst_ff_sptr_relative_rate", _wrap_sdrts_reverse_burst_ff_sptr_relative_rate, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_relative_rate(sdrts_reverse_burst_ff_sptr self) -> double"},

  { (char *)"sdrts_reverse_burst_ff_sptr_start", _wrap_sdrts_reverse_burst_ff_sptr_start, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_start(sdrts_reverse_burst_ff_sptr self) -> bool"},

  { (char *)"sdrts_reverse_burst_ff_sptr_stop", _wrap_sdrts_reverse_burst_ff_sptr_stop, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_stop(sdrts_reverse_burst_ff_sptr self) -> bool"},

  { (char *)"sdrts_reverse_burst_ff_sptr_nitems_read", _wrap_sdrts_reverse_burst_ff_sptr_nitems_read, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_nitems_read(sdrts_reverse_burst_ff_sptr self, unsigned int which_input) -> uint64_t"},

  { (char *)"sdrts_reverse_burst_ff_sptr_nitems_written", _wrap_sdrts_reverse_burst_ff_sptr_nitems_written, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_nitems_written(sdrts_reverse_burst_ff_sptr self, unsigned int which_output) -> uint64_t"},

  { (char *)"sdrts_reverse_burst_ff_sptr_detail", _wrap_sdrts_reverse_burst_ff_sptr_detail, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_detail(sdrts_reverse_burst_ff_sptr self) -> gr_block_detail_sptr"},

  { (char *)"sdrts_reverse_burst_ff_sptr_set_detail", _wrap_sdrts_reverse_burst_ff_sptr_set_detail, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_set_detail(sdrts_reverse_burst_ff_sptr self, gr_block_detail_sptr detail)"},

  { (char *)"sdrts_reverse_burst_ff_sptr_name", _wrap_sdrts_reverse_burst_ff_sptr_name, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_name(sdrts_reverse_burst_ff_sptr self) -> string"},

  { (char *)"sdrts_reverse_burst_ff_sptr_input_signature", _wrap_sdrts_reverse_burst_ff_sptr_input_signature, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_input_signature(sdrts_reverse_burst_ff_sptr self) -> gr_io_signature_sptr"},

  { (char *)"sdrts_reverse_burst_ff_sptr_output_signature", _wrap_sdrts_reverse_burst_ff_sptr_output_signature, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_output_signature(sdrts_reverse_burst_ff_sptr self) -> gr_io_signature_sptr"},

  { (char *)"sdrts_reverse_burst_ff_sptr_unique_id", _wrap_sdrts_reverse_burst_ff_sptr_unique_id, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_unique_id(sdrts_reverse_burst_ff_sptr self) -> long"},

  { (char *)"sdrts_reverse_burst_ff_sptr_to_basic_block", _wrap_sdrts_reverse_burst_ff_sptr_to_basic_block, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_to_basic_block(sdrts_reverse_burst_ff_sptr self) -> gr_basic_block_sptr"},

  { (char *)"sdrts_reverse_burst_ff_sptr_check_topology", _wrap_sdrts_reverse_burst_ff_sptr_check_topology, METH_VARARGS, (char *)"sdrts_reverse_burst_ff_sptr_check_topology(sdrts_reverse_burst_ff_sptr self, int ninputs, int noutputs) -> bool"},

  { (char *)"sdrts_reverse_burst_ff_sptr_swigregister", sdrts_reverse_burst_ff_sptr_swigregister, METH_VARARGS, NULL},

  { (char *)"reverse_burst_ff", _wrap_reverse_burst_ff, METH_VARARGS, (char *)"reverse_burst_ff(int max_samples) -> sdrts_reverse_burst_ff_sptr"},

  { NULL, NULL, 0, NULL }

};

I followed my old experience with .dll s and exported all the functions with a simple __declspec(dllexport) head. 我遵循了我对.dll的旧体验,并使用简单的__declspec(dllexport)头导出了所有函数。 In Python, I can also call the _wrap_sdrts_reverse_burst_ff_sptr___deref__ I exported: 在Python中,我也可以调用我导出的_wrap_sdrts_reverse_burst_ff_sptr___deref__

import ctypes

_dll_func_list = ctypes.WinDLL("func.dll")

_reverse_burst_ref = _dll_func_list._wrap_sdrts_reverse_burst_ff_sptr___deref__

Yet, that's the furthest I can approach. 然而,这是我能走得最远的地方。 When I try to access the sub functions in that class, for example, 当我尝试访问该类中的子函数时,例如,

_class_ref._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)

the damned machine told me: 该死的机器告诉我:

'_wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst' cannot be found. 找不到'_wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst'。

When I try to call the function directly and pass in a parameter like this: 当我尝试直接调用函数并传入这样的参数时:

_dll_func_list ._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)

The machine says 机器说

WindowsError: exception: access violation reading 0x00000004 WindowsError:exception:访问冲突读取0x00000004

Does anyone know how to access exported SWIG wrapped functions using Python? 有谁知道如何使用Python访问导出的SWIG包装函数?

So the final short answer appears to be that the C++ build should produce _my_dll.pyd (not _my_dll.dll ) in order to be able to import my_dll in Python on Windows. 所以最后的简短答案似乎是C ++构建应该生成_my_dll.pyd (而不是_my_dll.dll ),以便能够在Windows上用Python导入my_dll This is in contrast to the Linux build, where one would build _my_dll.so 这与Linux构建形成对比,后者将构建_my_dll.so

Simply renaming .dll file to .pyd works, but it is better to build it, as pointed out in comments above. 简单地将.dll文件重命名为.pyd是可行的,但最好是构建它,如上面的评论中所指出的那样。

SWIG also generates a .py file, in addition to the .cxx file. 除了.cxx文件外,SWIG还会生成.py文件。 Once you've built a DLL (or shared object) on your platform all you need to do to use that in Python itself is 一旦你在你的平台上构建了一个DLL(或共享对象),你需要做的就是在Python本身使用它

import ModuleName

where ModuleName is what you told SWIG to call the module, either via %module in the .i file for from the command line when you called it. 其中ModuleName是您告诉SWIG调用该模块的内容,可以通过.i文件中的%module从命令行调用它。

In the SWIG generated Python there is code to handle the loading of the DLL for you - no need to be using ctypes or anything like that with it. 在SWIG生成的Python中,有代码可以为您处理DLL的加载 - 无需使用ctypes或类似的东西。 The generated code matches the interface you asked SWIG to wrap as closely as possible in Python and magically hands the calls off to the C++ side for you. 生成的代码与您要求SWIG尽可能在Python中进行包装的接口相匹配,并为您调用C ++方面的调用。

Thus if sdrts_reverse_burst_ff is a free function you can do: 因此,如果sdrts_reverse_burst_ff是一个自由函数,你可以这样做:

import ModuleName

ModuleName.sdrts_reverse_burst_ff()

You need to make sure you build the DLL with the name SWIG expects it to have - it'll be pretty obvious from the exception that Python raises if that's not the case. 您需要确保使用SWIG期望它具有的名称来构建DLL - 如果不是这种情况,Python会引发异常。 You probably also want to link it against your implementation that contains sdrts_reverse_burst_ff() unless that's a header only function. 您可能还希望将它与包含sdrts_reverse_burst_ff()实现链接起来,除非这是一个仅限标题的函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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