Ho una funzione di libreria (scritta in C) che genera testo scrivendo l'output su FILE *
. Voglio racchiuderlo in Python (2.7.x) con codice che crea un file temporaneo o pipe, lo passa nella funzione, legge il risultato dal file e lo restituisce come una stringa Python.Passare FILE * in funzione da Python/ctypes
Ecco un esempio semplificato per illustrare quello che sto cercando:
/* Library function */
void write_numbers(FILE * f, int arg1, int arg2)
{
fprintf(f, "%d %d\n", arg1, arg2);
}
Python avvolgitore:
from ctypes import *
mylib = CDLL('mylib.so')
def write_numbers(a, b):
rd, wr = os.pipe()
write_fp = MAGIC_HERE(wr)
mylib.write_numbers(write_fp, a, b)
os.close(wr)
read_file = os.fdopen(rd)
res = read_file.read()
read_file.close()
return res
#Should result in '1 2\n' being printed.
print write_numbers(1,2)
mi chiedo qual è il mio migliore scommessa è per MAGIC_HERE()
.
Sono tentato di utilizzare solo ctypes
e creare un wrapper libc.fdopen()
che restituisce un Python c_void_t, quindi lo passa nella funzione di libreria. Credo che in teoria dovrebbe essere sicuro - basta chiedersi se ci sono problemi con questo approccio o un Python-ismo esistente per risolvere questo problema.
Inoltre, questo andrà in un processo di lunga durata (assumiamo solo "per sempre"), quindi eventuali descrittori di file trapelati saranno problematici.
'os .popen() 'non è corretto. Richiede almeno un argomento, la riga di comando per invocare e ottenere pipe. Inoltre, è deprecato in favore di "sottoprocesso", come [i documenti] (https://docs.python.org/2/library/os.html?highlight=os.popen#os.popen) dicono. –
Mi spiace, intendevo 'os.pipe()'. Aggiornato. –
A meno che non si stia pianificando di eseguirlo su Windows, che ha il problema di librerie di runtime C potenzialmente non corrispondenti, allora non penso che avremo problemi nel chiamare 'libc.fdopen' e passare il puntatore' FILE' risultante .Ma invece di usare 'c_void_p', creerei un opaco' classe FILE (Structure): pass' e metto 'libc.fdopen.restype = POINTER (FILE)'. Questo non verrà convertito in un risultato intero. OTOH, 'c_void_p' come' restype' viene convertito in un intero, quindi dovresti assicurarti che 'mylib.write_numbers.argtypes' sia impostato anche per evitare di troncare un valore puntatore a 64 bit. – eryksun