2017-06-05 61 views
0

使用numpy的,我想創建從蟒蛇.so文件和C. 執行.so文件要做到這一點我以前用Cython轉換.pyx到是.so與用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 

然後我用安裝的.py實際轉換.pyx到是.so

## 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()] 
) 

通過運行以下命令行,我能創造.so文件

python setup.py build_ext --inplace 

當我嘗試使用以下C代碼運行此文件時,出現了分段錯誤。

/* 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); 
} 

我編譯如下命令這個.c文件:

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

當我試圖運行此代碼,我得到了一個分割故障

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

如果我註釋掉以下line in print_me.pyx

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

我的C代碼運行時沒有錯誤,但是一旦我取消註釋此行,它不起作用。 我認爲嘗試在cython中使用numpy會以某種方式產生錯誤。

我該如何解決? 非常感謝你的回覆

+0

'print_me.so'是否作爲Python導入工作? – hpaulj

+0

是的,它適用於python。但是當我通過加載調用函數時。所以從c文件中,它不起作用:( – jinki

回答

2

你必須initialize the numpy C API by calling import_array()

此行添加到您的用Cython文件:

cnp.import_array() 

以及由@ user4815162342和@DavidW在評論中指出,必須調用Py_Initialize() and Py_Finalize() in main()

+2

此外,'main()'中缺少'Py_Initialize()'! – user4815162342

+0

cnp.import_array()不起作用:(它仍然給我分段錯誤 – jinki

+0

我不知道因爲在C文件中,我只是調用.so文件,這就是我所有的c文件所做的。 – jinki

0

首先感謝您的幫助。我可以得到一些有用的信息,儘管這不能直接解決我的問題。

通過引用別人的建議, 而不是從.so文件調用print_me函數,我決定直接從C中調用。這就是我所做的。

# 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]) 

這是我的.c文件

// 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; 
} 

然後我編譯如下

# 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 

這將導致以下

[[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 

謝謝所有您的幫助再次!! :)