2012-09-03 9 views
8

मै मैट्रिक्स गणना के लिए कुछ फ़ंक्शन लिखने के लिए numpy के सी एपीआई का उपयोग कर रहा हूं। आज मैं अपने कार्यों के कुछ हिस्सों को अलग-अलग .c फ़ाइल में ले जाना चाहता था और उन्हें घोषित करने के लिए हेडर का उपयोग करना चाहता था। अब मुझे एक अजीब समस्या है जिसे numpy के import_array फ़ंक्शन के साथ करना है। मैंने जितनी ज्यादा हो सके समस्या को सरल बनाने की कोशिश की है। पहले तो वहाँ काम कर रहे कार्यक्रम है:न्यूम्पी सी एपीआई: कई ऑब्जेक्ट फाइलों को लिंक करें

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

अगर मैं init समारोह से import_array हटा एक segfault है, जो व्यवहार है वहाँ हो सकता है कि कई मेलिंग सूचियों और मंचों में रिपोर्ट किया गया है।

अब मैं सिर्फ 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 

यदि मैं मॉड्यूल लोड करने और फ़ंक्शन को कॉल करने का प्रयास करता हूं तो फ़ंक्शन कॉल मुझे एक सेगफॉल्ट देता है। यदि मैं my_sub_function के शीर्ष पर import_array पर कॉल करता हूं, तो मुझे समस्या का समाधान हो सकता है, लेकिन मुझे नहीं लगता कि यह तरीका है कि फ़ंक्शन का उपयोग किया जाना चाहिए।

तो मैं जानना चाहता हूं कि यह क्यों हो रहा है और कई स्रोत फ़ाइलों में एक numpy मॉड्यूल को विभाजित करने के लिए "साफ" तरीका क्या है।

उत्तर

8

डिफ़ॉल्ट रूप से, import_array दिनचर्या केवल एक फ़ाइल के भीतर NumPy C API उपलब्ध कराएगी। ऐसा इसलिए है क्योंकि यह स्थैतिक वैश्विक चर में संग्रहीत फ़ंक्शन पॉइंटर्स की एक तालिका के माध्यम से काम करता है (यानी निर्यात नहीं किया गया है, और केवल उसी फ़ाइल में दिखाई देता है)। अपने विस्तार के लिए

  1. सभी फाइलों में, एक अद्वितीय चर कि अन्य एक्सटेंशन के साथ संघर्ष की संभावना नहीं है करने के लिए PY_ARRAY_UNIQUE_SYMBOL को परिभाषित:

    mentioned in the documentation के रूप में, आप इस व्यवहार में कुछ पूर्वप्रक्रमक परिभाषा के साथ बदल सकते हैं। परिवर्तनीय नाम में आपके एक्सटेंशन का मॉड्यूल नाम शामिल करना एक अच्छा विचार होगा।इससे पहले कि आप उन्हें प्रभावी करने के लिए में arrayobject.h शामिल

  2. वह हो जिस पर import_array फोन को छोड़कर हर फ़ाइल में, प्रतीक NO_IMPORT_ARRAY

इन प्रतीकों से परिभाषित करने की जरूरत है परिभाषित करते हैं।

संबंधित मुद्दे