2012-01-23 18 views
5

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?

Respuesta

2

SWIG también genera un archivo .py, además del archivo .cxx.Una vez que se ha construido una DLL (o un objeto compartido) en su plataforma de todo lo que tiene que hacer para usar eso en sí mismo es Python

import ModuleName 

donde ModuleName es lo que le dijo el TRAGO para llamar al módulo, ya sea a través de %module el archivo .i para la línea de comando cuando lo llamó.

En el Python generado por SWIG hay un código para manejar la carga de la DLL por usted, sin necesidad de utilizar ctypes ni nada de eso con eso. El código generado coincide con la interfaz que solicitó a SWIG para que se ajuste lo más posible a Python y mágicamente entrega las llamadas al lado de C++ por usted.

Así, si sdrts_reverse_burst_ff es una función gratuita que puede hacer:

import ModuleName 

ModuleName.sdrts_reverse_burst_ff() 

Usted necesita asegurarse de que la construcción de la DLL con el nombre TRAGO espera que tenga - que va a ser bastante obvio por la excepción de que Python plantea si ese no es el caso. Probablemente también desee vincularlo con su implementación que contiene sdrts_reverse_burst_ff() a menos que sea una función de solo encabezado.

+0

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

+0

@ 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

+1

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

1

Así que la respuesta corta final parece ser que la compilación de C++ debe producir _my_dll.pyd (no _my_dll.dll) para poder importar my_dll en Python en Windows. Esto está en contraste con la versión de Linux, donde se construiría _my_dll.so

Simplemente cambiar el nombre del archivo .dll a .pyd funciona, pero es mejor construirlo, como se señaló en los comentarios anteriores.

Cuestiones relacionadas