2017-06-05 1 views
0

Ich möchte .so Datei von Python erstellen und die .so-Datei in C ausführen, um es zu tun pflegte ich cython .pyx zu konvertieren zu .soVerwenden numpy mit Cython

## print_me.pyx 
cimport numpy as cnp 
import numpy as np 
cimport cython 
cpdef public char* print_me(f): 
    # I know this numpy line does nothing 
    cdef cnp.ndarray[cnp.complex128_t, ndim=3] a = np.zeros((3,3,3), dtype=np.complex128) 
    return f 

Dann habe ich Setup .py tatsächlich

## setup.py 
from distutils.core import setup 
from Cython.Build import cythonize 
import numpy as np 

setup(
    ext_modules=cythonize("print_me.pyx"), 
    include_dirs=[np.get_include()] 
) 

Durch das Ausführen die folgende Befehlszeile, um .so zu konvertieren .pyx konnte ich .so Datei

python setup.py build_ext --inplace 
erstellen 210

Wenn ich versucht habe, so Datei mit dem folgenden C-Code auszuführen, habe ich einen Segmentation Fault.

/* toloadso.c */ 
#include <stdio.h> 
#include <stdlib.h> 
#include <dlfcn.h> 
#include <time.h> 
#include <python2.7/Python.h> 

int main(void) 
{ 
    // define function 
    void *handle; 
    char* (*print_me)(PyObject*); 
    char *error; 

    PyObject* filename = PyString_FromString("hello"); 

    // load so file 
    handle = dlopen("./print_me.so", RTLD_LAZY); 
    if (!handle) { 
     fprintf(stderr, "%s\n", dlerror()); 
     exit(EXIT_FAILURE); 
    } 
    dlerror(); 

    // get function handler from so file 
    print_me = (char* (*)(PyObject*))dlsym(handle, "print_me"); 

    // check if handler got error 
    error = dlerror(); 
    if (error != NULL) { 
     fprintf(stderr, "%s\n", error); 
     exit(EXIT_FAILURE); 
    } 

    // execute loaded function 
    printf("%s\n", (char*)(*print_me)(filename)); 
    dlclose(handle); 
    exit(EXIT_SUCCESS); 
} 

ich diese C-Datei mit folgendem Befehl kompiliert:

gcc -fPIC -I/usr/include/ -o toloadso toloadso.c -lpython2.7 -ldl 
(It compiled without error or warning) 

Als ich versuchte, diesen Code auszuführen, bekam ich einen Segmentation Fault

[[email protected] ~]# ./toloadso 
Segmentation fault 

Wenn ich den folgenden Kommentar aus Linie in print_me.pyx

cdef cnp.ndarray[cnp.complex128_t, ndim=3] a = np.zeros((3,3,3), dtype=np.complex128) 

Mein C-Code läuft ohne Fehler, aber sobald ich diese Zeile auskommentiere, funktioniert es nicht. Ich denke, dass der Versuch, numpy in Cython zu verwenden, irgendwie einen Fehler erzeugt.

Wie kann ich es beheben ?? Ich danke Ihnen so viel für Ihre Antwort

+0

Funktioniert 'print_me.so' als Python-Import? – hpaulj

+0

Ja, es funktioniert auf Python. aber wenn ich die Funktion durch Laden aufrufen.so Datei von c-Datei, es funktioniert nicht :( – jinki

Antwort

2

Sie müssen initialize the numpy C API by calling import_array().

diese Zeile in cython Datei hinzufügen:

cnp.import_array() 

Und wie von @ user4815162342 und @DavidW in den Kommentaren darauf hingewiesen, Sie Py_Initialize() and Py_Finalize() in main() nennen müssen.

+2

Auch 'Py_Initialize()' fehlt in 'main()'! – user4815162342

+0

cnp.import_array() funktioniert nicht :(es gibt immer noch Segmentierung Fehler. – jinki

+0

Ich don Ich denke, Py_Initialize() wird benötigt, weil ich in C-Datei nur .SO-Datei aufrufen, das ist alles meine c-Datei tut. – jinki

0

Vielen Dank für Ihre Hilfe zuerst. Ich konnte nützliche Informationen bekommen, obwohl das mein Problem nicht direkt lösen konnte.

Durch Verweis auf andere Beratung, anstatt print_me Funktion von .so Datei aufrufen, entschied ich mich, direkt von C anrufen. Das ist, was ich getan habe.

# print_me.pyx 
import numpy as np 
cimport numpy as np 

np.import_array() 

cdef public char* print_me(f): 
    cdef int[2][4] ll = [[1, 2, 3, 4], [5,6,7,8]] 
    cdef np.ndarray[np.int_t, ndim=2] nll = np.zeros((4, 6), dtype=np.int) 
    print nll 
    nll += 1 
    print nll 
    return f + str(ll[1][0]) 

Dies ist meine C-Datei

// main.c 
#include <python2.7/Python.h> 
#include "print_me.h" 

int main() 
{ 
    // initialize python 
    Py_Initialize(); 
    PyObject* filename = PyString_FromString("hello"); 
    initsquare_number(); 
    //initprint_me(); 

    // call python-oriented function 
    printf("%s\n", print_me(filename)); 

    // finalize python 
    Py_Finalize(); 
    return 0; 
} 

ich dann kompiliert als

# to generate print_me.c and print_me.h 
cython print_me.pyx 

# to build main.c and print_me.c into main.o and print_me.o 
cc -c main.c print_me.c -I/usr/include/python2.7 -I/usr/lib64/python2.7/site-packages/numpy/core/include 

# to linke .o files 
cc -lpython2.7 -ldl main.o print_me.o -o main 

# execute main 
./main 

für all Ihre Hilfe Dies ergibt die folgende

[[0 0 0 0 0 0] 
[0 0 0 0 0 0] 
[0 0 0 0 0 0] 
[0 0 0 0 0 0]] 
[[1 1 1 1 1 1] 
[1 1 1 1 1 1] 
[1 1 1 1 1 1] 
[1 1 1 1 1 1]] 
hello5 

Danke folgt nochmal!! :)