2013-03-03 4 views
8

Ho una funzione C++ in cui vengono forniti due argomenti come nell'esempio seguente.Come ricevere argomenti di riferimento e puntatori in Python + SWIG?

void func(int& n, char** data) 
{ 
    *data = other_func1(); // returns a char array 
    n = other_func2(); // returns the length of the array 
} 

posso utilizzare facilmente questa funzione in C o C++, ma non so come posso chiamare da un modulo Python generata con SWIG. Suppongo che dovrò scrivere un'altra funzione C++ che restituisce, ad esempio, std :: pair. Ma se possibile, mi piacerebbe sapere una soluzione alternativa in Python. Qualcuno potrebbe aiutare?

risposta

8

Per parecchio casi (ad esempio int *n) sarebbe sufficiente scrivere:

%apply int *OUTPUT { int *n }; 

che utilizza alcuni typemaps predefinite SWIG fornisce per parametri di output. (C'è anche INOUT e INPUT che sono simili).

In questo caso, tuttavia, non corrispondiamo a nessuno dei casi predefiniti, quindi è necessario eseguire manualmente la stessa operazione. In pratica sono due typemaps per argomento: una typemap di input che crea qualcosa di temporaneo per la chiamata alla funzione effettiva e utilizza quello invece di qualche input reale e un argout che effettua il marshalling del risultato dal temporaneo a Python. Nel caso di Python ha senso usare una tupla per restituire più argomenti.

Un esempio:

%module test 

%typemap(in,numinputs=0) int& n (int temp) "$1 = &temp;" 
%typemap(in,numinputs=0) char **data (char *temp) "$1 = &temp;" 

%typemap(argout) char **data { 
    %append_output(PyString_FromString(*$1)); 
} 

%typemap(argout) int& n { 
    %append_output(PyInt_FromLong(*$1)); 
} 

%inline %{ 
    void foo(int& n, char **data) { 
    static char str[] = "Hello world"; 
    *data = str; 
    n = sizeof str; 
    } 
%} 

Punti da notare:

Le variabili temporanee (int temp, char *temp) automaticamente ottenere rinominato che ferma il nome scontro apparente. %append_output è una macro SWIG che si espande per aggiungere qualcosa alla parte posteriore della tupla $result in Python. Se la tua funzione foo fosse allocata dinamicamente alla memoria, dovrai gestirla. La typemap freearg è spesso utile se la typemap in deve allocare dinamicamente la memoria.

Questo era sufficiente per permettermi di compilare ed eseguire le cose come:

import test 

len,str = test.foo() 

print len 
print str