Lontano da esperto ac ma per me usare Ubuntu, le seguenti opere:
main.c:
#include "foo_api.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
Py_Initialize();
initfoo();
import_foo();
double arr[5] = {1,2,3,4,5};
int i = 0;
foo(arr);
for(i = 0; i < 5; i++)
{
printf("%f\n", arr[i]);
}
Py_Finalize();
return 0;
}
foo.pyx:
cdef public api foo(double* x):
x[0] = 0.0
Dalla stessa directory:
$ cython foo.pyx
Il n:
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o foo *.c -lpython2.7
Quindi basta eseguire.
$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000
ho usato pkg-config --cflags python
per ottenere le bandiere:
$ pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7
Senza rimettere Py_Initialize (inizializzare l'interprete Python In un'applicazione che contiene Python, questo dovrebbe essere chiamato prima di utilizzare qualsiasi altra API Python/C. funzioni;), si otterrà:
Fatal Python error: PyThreadState_Get: no current thread
Aborted (core dumped)
Senza initfoo()
o import_foo()
si ottiene un:
Segmentation fault (core dumped)
Se non chiami Py_Finalize:
Py_Initialize
un no-op quando viene chiamato per una seconda volta (senza chiamare Py_Finalize() prima).
Per ottenere l'esempio delorean dalla documentazione per eseguire:
main.py:
#include "delorean_api.h"
#include <stdio.h>
Vehicle car;
int main(int argc, char *argv[]) {
Py_Initialize();
initdelorean();
import_delorean();
car.speed = atoi(argv[1]);
car.power = atof(argv[2]);
activate(&car);
Py_Finalize();
return 0;
}
DeLorean.pisside:
ctypedef public struct Vehicle:
int speed
float power
cdef api void activate(Vehicle *v):
if v.speed >= 88 and v.power >= 1.21:
print "Time travel achieved"
else:
print("Sorry Marty")
La procedura è la stessa, l'unico cambiamento è stato che ho dovuto usare ctypedef
con la struct veicolo oppure in principale o utilizzare avevo t utilizzare struct Vehicle car;
nel principale:
$ cython delorean.pyx
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o delorean *.c -lpython2.7
$ ./delorean 1 1
Sorry Marty
$ ./delorean 100 2
Time travel achieved
È può anche farlo funzionare senza usare Py_Initialize
ecc ...
In foo.pyx
solo bisogno di rendere la funzione pubblica:
cdef public foo(double* x):
x[0] = 0.0
ho aggiunto #include <python2.7/Python.h>
appena importato foo.h
in main.ce rimossi Py_Initialize();
ecc Basta importare python.h
non avrebbe funzionato per me, ma che non può essere il caso per tutti.
#include <python2.7/Python.h>
#include "foo.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
double arr[5] = {1,2,3,4,5};
int i = 0;
foo(arr);
for(i = 0; i < 5; i++)
{
printf("%f\n", arr[i]);
}
return 0;
}
Compilazione era la stessa:
$ cython foo.pyx
$ cc -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7 -o foo *.c -lpython2.7
$ ./foo
0.000000
2.000000
3.000000
4.000000
5.000000
Se si utilizza la versione di api poi basta includere l'intestazione api o viceversa secondo la documentazione Si noti tuttavia che si dovrebbe includere sia modulename. h o modulename_api.h in un dato file C, non entrambi, altrimenti potresti ottenere definizioni doppie in conflitto.
Per fare la stessa cosa con l'esempio DeLorean ho dovuto usare libc.stdio
per stampare le stringhe per evitare un errore di segmentazione:
from libc.stdio cimport printf
ctypedef public struct Vehicle:
int speed
float power
cdef public void activate(Vehicle *v):
if v.speed >= 88 and v.power >= 1.21:
printf("Time travel achieved\n")
else:
printf("Sorry Marty\n")
principale:
#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"
Vehicle car;
int main(int argc, char *argv[]) {
car.speed = atoi(argv[1]);
car.power = atof(argv[2]);
activate(&car);
return 0;
}
Potrebbe avere più senso restituire i valori:
ctypedef public struct Vehicle:
int speed
float power
cdef public char* activate(Vehicle *v):
if v.speed >= 88 and v.power >= 1.21:
return "Time travel achieved"
return "Sorry Marty"
principale:
#include <python2.7/Python.h>
#include <stdio.h>
#include "delorean.h"
Vehicle car;
int main(int argc, char *argv[]) {
car.speed = atoi(argv[1]);
car.power = atof(argv[2]);
printf("%s\n",activate(&car));
return 0;
}
Ho provato ** gcc -L. -Wall -o main main.c -lpython2.7 -l: foo.so **, ma penso che manchi qualcosa nel file main.c, perché ottengo "riferimento indefinito a' foo '" – Bociek
Si desidera chiamare pippo da main.c? come http://docs.cython.org/src/userguide/external_C_code.html#c-api-declarations? –
@PadraicCunnigham Precisamente! Voglio foo (x) call. – Bociek