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

时间:2012-01-23 22:58:31

标签: c++ python dll shared-libraries swig

我在使用通过SWIG接口导出的.dll共享库中的函数时遇到问题。

  

版本信息

     

Python:2.6.4

     

Swig:2.0.4

总体情况是:我在Linux下使用C ++开发了一些代码并使用SWIG进行封装。我将C ++源代码编译成Linux下的.so对象,并在Python中使用.so库。

现在,我需要将所有这些功能迁移到Windows,而Windows中.so的等效功能是.dll。因此,我计划将所有C ++源代码编译成.dll并通过Python访问它们。

所以正常的程序是:拥有C ++源代码 - >使用SWIG包裹它们 - >汇编成.dll - >通过Python访问。

使用SWIG生成了一个巨大的.cxx源文件,其中包含我开发的所有功能。现在的任务是将此SWIG生成的文件编译为.dll,以便稍后可以使用所有函数。但是,.cxx文件使用了一些奇怪的方式来包装我的所有函数,我不知道如何使用它们。

函数包装如下。 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;

}

这不是全部:在这个.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 }

};

我遵循了.dll的旧体验,并使用简单的__declspec(dllexport)头导出了所有函数。在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__

然而,这是我能走得最远的地方。当我尝试访问该类中的子函数时,例如,

_class_ref._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)
该死的机器告诉我:

  无法找到

'_ wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst'。

当我尝试直接调用函数并传入这样的参数时:

_dll_func_list ._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)

机器说

  

WindowsError:exception:访问冲突读取0x00000004

有谁知道如何使用Python访问导出的SWIG包装函数?

2 个答案:

答案 0 :(得分:2)

除了.cxx文件外,SWIG还会生成.py文件。一旦你在你的平台上构建了一个DLL(或共享对象),你需要做的就是在Python本身中使用它

import ModuleName

其中ModuleName是您告诉SWIG调用该模块的内容,可以通过.i文件中的%module来调用,也可以从命令行调用。

在SWIG生成的Python中,有代码可以为您处理DLL的加载 - 无需使用ctypes或类似的东西。生成的代码与您要求SWIG在Python中尽可能接近地包装的接口相匹配,并为您调用C ++方面的调用。

因此,如果sdrts_reverse_burst_ff是免费功能,您可以这样做:

import ModuleName

ModuleName.sdrts_reverse_burst_ff()

您需要确保使用SWIG期望它具有的名称来构建DLL - 如果不是这种情况,Python会引发异常。您可能还希望将其与包含sdrts_reverse_burst_ff()的实现相关联,除非这只是一个标题函数。

答案 1 :(得分:2)

所以最后的简短回答似乎是C ++构建应该生成_my_dll.pyd(而不是_my_dll.dll),以便能够在Windows上的Python中导入my_dll。这与Linux构建形成对比,其中构建_my_dll.so

简单地将.dll文件重命名为.pyd可以正常工作,但最好是构建它,如上面的评论所述。