Использование SWIG-функций из Windows .dll - PullRequest
5 голосов
/ 24 января 2012

У меня проблема с использованием функций из общей библиотеки .dll, которая экспортируется через интерфейс SWIG.

Информация о версии

Python: 2.6.4

Swig: 2.0.4

Общая картина такова: у меня есть некоторый код, разработанный под Linux с использованием C ++ и упакованный с использованием SWIG. Я скомпилировал исходный код C ++ в объект .so в Linux и использую библиотеку .so в Python.

Теперь мне нужно перенести все эти функции в окна, и эквивалент для .so в Windows равен .dll. Итак, я планировал собрать все исходные коды C ++ в .dll и получить к ним доступ через Python.

Таким образом, нормальная процедура будет такой: иметь исходный код C ++ -> обернуть их, используя SWIG -> compile в .dll -> доступ через Python.

Существует огромный .cxx исходный файл, сгенерированный с помощью SWIG, который содержит все функции, которые я разработал. Теперь задача состоит в том, чтобы скомпилировать этот файл, сгенерированный SWIG, в .dll, чтобы я мог использовать все функции позже. Тем не менее, файл .cxx использует какой-то странный способ обернуть все мои функции, и я понятия не имею, как их использовать.

Функции упакованы следующим образом. Скажем, у меня есть класс C ++ с именем sdrts_reverse_burst_ff, после переноса класс становится функцией в файле .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 s и экспортировал все функции с простой __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: исключение: чтение нарушения доступа 0x00000004

Кто-нибудь знает, как получить доступ к экспортированным SWIG-функциям с помощью Python?

Ответы [ 2 ]

2 голосов
/ 08 июля 2016

Таким образом, последний краткий ответ, по-видимому, заключается в том, что сборка C ++ должна выдавать _my_dll.pyd (не _my_dll.dll), чтобы иметь возможность импортировать my_dll в Python в Windows. Это в отличие от сборки Linux, где можно было бы собрать _my_dll.so

Простое переименование файла .dll в .pyd работает, но его лучше собрать, как указано в комментариях выше.

2 голосов
/ 24 января 2012

SWIG также генерирует файл .py, в дополнение к файлу .cxx.После того, как вы создали DLL (или общий объект) на своей платформе, все, что вам нужно сделать, чтобы использовать ее в самом Python, это:

import ModuleName

, где ModuleName - это то, что вы сказали SWIG для вызова модуля,либо через %module в файле .i для командной строки, когда вы ее вызывали.

В Python, сгенерированном SWIG, есть код для обработки загрузки DLL для вас - нет необходимости использовать ctypesили что-нибудь подобное с этим.Сгенерированный код соответствует интерфейсу, который вы просили SWIG, чтобы как можно точнее обернуть его в Python, и волшебным образом перенаправляет вызовы на сторону C ++.

Таким образом, если sdrts_reverse_burst_ff - бесплатная функция, вы можете сделать:

import ModuleName

ModuleName.sdrts_reverse_burst_ff()

Вам нужно убедиться, что вы собрали DLL с именем, которое SWIG ожидает от нее - это будет довольно очевидно из исключения, которое вызывает Python, если это не так.Возможно, вы также захотите связать его с вашей реализацией, которая содержит sdrts_reverse_burst_ff(), если это не только функция заголовка.

...