2012-09-03 25 views
8

我使用numpy的C API來編寫矩陣計算的一些函數。今天,我想將我的函數的一些部分移動到一個單獨的.c文件中,並使用頭部來聲明它們。現在我有一個奇怪的問題,與numpy的import_array函數有關。我試圖儘可能簡化問題。起初有工作程序:Numpy C API:鏈接幾個目標文件

mytest.c

#include "mytest.h" 

PyObject* my_sub_function() { 
    npy_intp dims[2] = {2, 2}; 
    double data[] = {0.1, 0.2, 0.3, 0.4}; 

    PyArrayObject* matrix = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_FLOAT64); 
    memcpy(PyArray_DATA(matrix), data, sizeof(double) * dims[0] * dims[1]); 

    return (PyObject*)matrix; 
} 

static PyObject* my_test_function(PyObject* self, PyObject* args) { 
    return my_sub_function(); 
} 

static PyMethodDef methods[] = { 
    {"my_test_function", my_test_function, METH_VARARGS, ""}, 
    {0, 0, 0, 0} 
}; 

static struct PyModuleDef module = { 
    PyModuleDef_HEAD_INIT, "mytest", 0, -1, methods 
}; 

PyMODINIT_FUNC PyInit_mytest() { 
    import_array(); 
    return PyModule_Create(&module); 
} 

mytest.h

#ifndef mytest_h 
#define mytest_h 

#include <Python.h> 
#include <numpy/arrayobject.h> 
#include <numpy/npy_common.h> 

PyObject* my_sub_function(); 

#endif 

的Makefile

all: mytest.o sub.o 
    gcc -shared -Wl,-soname,mytest.so -o mytest.so mytest.o 

mytest.o: sub.o 
    gcc -fPIC -c mytest.c `pkg-config --cflags python3` 

clean: 
    rm -rf *.so 
    rm -rf *.o 

一切按預期工作。我可以打電話make然後加載模塊和調用該函數:

test.py

import mytest 
print(mytest.my_test_function()) 

如果我會從初始化函數刪除import_array會有段錯誤,這是行爲已經在許多郵件列表和論壇中報道過。

我現在只是想從mytest.c刪除整個功能my_sub_function,並將其移動到一個名爲sub.c文件:

#include "mytest.h" 

PyObject* my_sub_function() { 
    npy_intp dims[2] = {2, 2}; 
    double data[] = {0.1, 0.2, 0.3, 0.4}; 

    PyArrayObject* matrix = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_FLOAT64); 
    memcpy(PyArray_DATA(matrix), data, sizeof(double) * dims[0] * dims[1]); 

    return (PyObject*)matrix; 
} 

的Makefile是:

all: mytest.o sub.o 
    gcc -shared -Wl,-soname,mytest.so -o mytest.so mytest.o sub.o 

mytest.o: 
    gcc -fPIC -c mytest.c `pkg-config --cflags python3` 

sub.o: 
    gcc -fPIC -c sub.c `pkg-config --cflags python3` 

clean: 
    rm -rf *.so 
    rm -rf *.o 

如果我嘗試加載模塊並立即調用函數,則函數調用會給我一個段錯誤。如果我撥打import_arraymy_sub_function的頂部,我可以解決問題,但我不認爲這是應該使用此功能的方式。

所以我想知道爲什麼會發生這種情況,以及將「numpy」模塊拆分爲多個源文件的「乾淨」方式是什麼。

回答

8

默認情況下,import_array例程只會使NumPy C API在單個文件中可用。這是因爲它通過存儲在靜態全局變量中的函數指針表(即,未導出,並且僅在同一文件中可見)工作。

由於mentioned in the documentation,你可以用一些預處理器定義改變這種行爲:

  1. 中的所有文件爲您的擴展,定義PY_ARRAY_UNIQUE_SYMBOL一個獨特的變量是不太可能與其他擴展衝突。將變量名稱包含在變量名中是個好主意。

  2. 在除了一個地方你叫import_array每一個文件,你包括arrayobject.h,以便它們生效之前定義符號NO_IMPORT_ARRAY

這些符號需要定義。