Tengo un problema al usar funciones de una biblioteca compartida .dll
que se exporta con la interfaz SWIG.Uso de funciones envueltas en SWIG desde Windows .dll
Version Info
Python: 2.6.4
Swig: 2.0.4
La gran imagen es: Tengo un código desarrollado bajo Linux usando C++ y envuelto usando SWIG. Recopilé la fuente de C++ en un objeto .so
en Linux y uso la biblioteca .so
en Python.
Ahora, tengo que migrar todas estas funciones a Windows y el equivalente para .so
en Windows es un .dll
. Por lo tanto, planeé compilar todos los códigos fuente de C++ en un .dll
y acceder a ellos a través de Python.
Así que el procedimiento normal sería: tener la fuente C++ -> envolverlos usando SWIG -> compilar en .dll
-> acceder a través de Python.
Hay un gran archivo fuente .cxx
generado usando SWIG que contiene todas las funciones que desarrollé. La tarea ahora es compilar este archivo SWIG generado en un .dll
para que pueda usar todas las funciones más adelante. Sin embargo, el archivo .cxx utiliza alguna forma extraña de ajustar todas mis funciones y no tengo ni idea de cómo usarlas.
Las funciones se envuelven de la siguiente manera. Ssay tengo una clase de C++ llama sdrts_reverse_burst_ff
, después de envolver, la clase se convierte en una función en el archivo .cxx
y se define así:
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;
}
Eso no es todo: cerca del final de este archivo .cxx
hay una enorme variedad que contiene todas las funciones de la clase así:
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 }
};
Seguí a mi vieja experiencia con .dll
s y se exportan todas las funciones con un simple __declspec(dllexport)
cabeza. En Python, también puede llamar a la _wrap_sdrts_reverse_burst_ff_sptr___deref__
Exporté:
import ctypes
_dll_func_list = ctypes.WinDLL("func.dll")
_reverse_burst_ref = _dll_func_list._wrap_sdrts_reverse_burst_ff_sptr___deref__
Sin embargo, eso es lo más lejos que pueda acercarse. Cuando intento acceder a las funciones secundarias en esa clase, por ejemplo,
_class_ref._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)
la máquina maldita me dijo:
'_wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst' cannot be found.
cuando trato de llamar a la función directamente y pasar de un parámetro como este :
_dll_func_list ._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0)
La máquina dice
WindowsError: exception: access violation reading 0x00000004
¿Alguien sabe cómo acceder a las funciones exportadas envueltas de SWIG usando Python?
Utilizo el archivo python generado y tiene un asistente de importación. Pero falla al importar _my_dll, y dice: ImportError: Ningún módulo llamado _my_dll. Agregué la ruta absoluta a _my_dll para PYTHONPATH y LD_LIBRARY_PATH, debería poder encontrarla. – user1165959
@ user1165959 - debe asegurarse de que se llame * exactamente * "_my_dll.dll", luego, si de eso se queja Python. En sistemas Windows, tendí a simplemente ponerlo en el directorio actual en el momento en que se llama a Python. De cualquier forma, ctypes no es la forma de solucionarlo, necesita solucionar el problema de la ruta + carga y todo volverá a funcionar. – Flexo
Sí, se llama exactamente _my_dll.dll, y también intenté ponerlo en c: \ Python27 y todavía no lo pudo encontrar. Solo puede encontrar el dll cuando se usa ctypes.WinDLL ("_ my_dll.dll"). Pero como mencionaste que no es la manera de hacerlo, tengo la sensación de que este dll que hice no se compiló en un formato reconocible para SWIG. La forma en que uso swig es: swig -module _my_dll -fvirtual -python -modern -C++ -outdir. -o _my_dll.cxx _my_dll.i y luego compilé _my_dll.cxx en un dll junto con el src que utilicé para generar _my_dll.i utilizando VC++ 2008 express edition. ¿Algo que hice mal? – user1165959