2012-01-23 10 views
5

Ho riscontrato un problema nell'utilizzo di funzioni da una libreria condivisa .dll esportata con interfaccia SWIG.Utilizzo di funzioni SWIG con wrapping da Windows .dll

L'immagine grande è: ho un codice sviluppato sotto Linux utilizzando C++ e incapsulato usando SWIG. Ho compilato il sorgente C++ in un oggetto .so sotto Linux e uso la libreria .so in Python.

Ora, ho bisogno di migrare tutte queste funzioni a Windows e l'equivalente per .so in Windows è un .dll. Quindi, ho pianificato di compilare tutti i codici sorgente C++ in un .dll e accedervi tramite Python.

Quindi la procedura normale sarebbe: avere il sorgente C++ -> avvolgerli usando SWIG -> compilare in .dll -> accesso tramite Python.

C'è un enorme file sorgente .cxx generato utilizzando SWIG che contiene tutte le funzioni che ho sviluppato. Il compito ora è quello di compilare questo file SWIG generato in un .dll in modo che io possa utilizzare tutte le funzioni in seguito. Tuttavia, il file .cxx usa un modo strano di avvolgere tutte le mie funzioni e non ho idea di come usarle.

Le funzioni sono impacchettate come segue. Ssay Ho una classe C++ chiamato sdrts_reverse_burst_ff, dopo il confezionamento, la classe diventa una funzione nel file .cxx ed è definito in questo modo:

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; 

} 

Ma non è tutto: verso la fine di questo file .cxx v'è un allineamento enorme che contiene tutte le funzioni di classe in questo modo:

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 } 

}; 

ho seguito la mia vecchia esperienza con .dll s ed esportati tutte le funzioni con un semplice __declspec(dllexport) testa. In Python, posso anche chiamare il _wrap_sdrts_reverse_burst_ff_sptr___deref__ ho esportato:

import ctypes 

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

_reverse_burst_ref = _dll_func_list._wrap_sdrts_reverse_burst_ff_sptr___deref__ 

Eppure, questo è il più lontano che posso avvicinare. Quando provo ad accedere alle funzioni secondarie in quella classe, per esempio,

_class_ref._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0) 

la macchina maledetta mi ha detto:

'_wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst' cannot be found.

Quando provo a chiamare la funzione direttamente e passare un parametro come questo :

_dll_func_list ._wrap_sdrts_reverse_burst_ff_sptr_set_reverse_burst(0) 

La macchina dice

WindowsError: exception: access violation reading 0x00000004

Qualcuno sa come accedere alle funzioni di esportazione SWIG esportate usando Python?

risposta

2

SWIG genera anche un file .py, oltre al file .cxx.Una volta che hai costruito una DLL (o un oggetto condiviso) sulla vostra piattaforma tutto quello che dovete fare per utilizzare che in Python per sé è

import ModuleName 

dove ModuleName è quello che hai detto SWIG chiamare il modulo, sia tramite %module in il file .i dalla riga di comando quando lo hai chiamato.

Nel codice Python generato da SWIG è disponibile il codice per gestire il caricamento della DLL per voi, senza necessità di utilizzare ctypes o qualcosa di simile. Il codice generato corrisponde all'interfaccia che hai chiesto a SWIG di avvolgere il più strettamente possibile in Python e passa magicamente le chiamate al lato C++ per te.

Quindi se sdrts_reverse_burst_ff è una funzione gratuita che si può fare:

import ModuleName 

ModuleName.sdrts_reverse_burst_ff() 

È necessario assicurarsi di costruire la DLL con il nome SWIG aspetta di avere - sarà abbastanza evidente dal l'eccezione che Python solleva se non è questo il caso. Probabilmente vuoi anche collegarlo alla tua implementazione che contiene sdrts_reverse_burst_ff() a meno che non si tratti di una funzione di solo intestazione.

+0

Uso il file python generato e ha un helper di importazione. Ma fallisce quando import _my_dll, e dice: ImportError: nessun modulo chiamato _my_dll. Ho aggiunto il percorso assoluto a _my_dll sia a PYTHONPATH che a LD_LIBRARY_PATH, dovrebbe essere in grado di trovarlo. – user1165959

+0

@ user1165959 - è necessario assicurarsi che sia chiamato * esattamente * "_my_dll.dll", quindi se questo è ciò di cui si lamenta Python. Sui sistemi Windows ho teso a metterlo nella directory corrente al punto in cui Python viene chiamato. In ogni caso, ctypes non è il modo per risolverlo: devi risolvere il problema del percorso + di caricamento e tutto funzionerà di nuovo. – Flexo

+1

Sì, si chiama esattamente _my_dll.dll, e ho anche provato a metterlo in c: \ Python27 e ancora non riuscivo a trovarlo. Può trovare la dll solo quando si utilizza ctypes.WinDLL ("_ my_dll.dll"). Ma visto che hai detto che non è il modo di farlo, ho la sensazione che questa dll che ho creato non sia stata compilata in un formato riconoscibile da SWIG. Il modo in cui utilizzo swig è: swig -module _my_dll -fvirtual -python -modern -C++ -outdir. -o _my_dll.cxx _my_dll.i e poi ho compilato _my_dll.cxx in una dll insieme con lo src che ho usato per generare _my_dll.i utilizzando VC++ 2008 Express Edition. Qualcosa che ho fatto di sbagliato? – user1165959

1

Quindi la risposta breve finale sembra essere che il build C++ dovrebbe produrre _my_dll.pyd (non _my_dll.dll) per poter importare my_dll in Python su Windows. Questo è in contrasto con la build di Linux, dove si dovrebbe costruire _my_dll.so

Semplicemente rinominando il file .dll in .pyd funziona, ma è meglio crearlo, come sottolineato nei commenti sopra.