2016-02-10 6 views
8

पर आर और numpy दोनों का उपयोग करता है मेरे पास कुछ सी कोड है जो विंडोज़ पर numpy और R दोनों का उपयोग करता है, यह एमएसवीसी के साथ एक .dll में संकलित करता है जिसे गतिशील रूप से आर से लोड किया जा सकता है और सभी परीक्षणों को पास कर सकता है। हालांकि, मैं इसे डेबियन पर काम करने में विफल रहता हूं।संकलन सी कोड जो लिनक्स

समस्या मैं निम्नलिखित न्यूनतम-ish उदाहरण बनाया जांच करने के लिए:

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

SEXP main() { 
    Py_Initialize(); 
    import_array(); 

    SEXP one = PROTECT(allocVector(INTSXP, 1)); 
    INTEGER(one)[0] = 1; 
    npy_intp dims[1] = {1}; 
    int data[1] = {1}; 
    PyObject *another = PyArray_SimpleNewFromData(1, dims, NPY_INT, data); 

    Rprintf("Hello, %d ", INTEGER(one)[0] + *(int*)PyArray_DATA(another)); 
    PyRun_SimpleString("print('worlds')"); 

    UNPROTECT(1); 
    return one; 
} 

मैं इसे

cl /I "C:\Program Files\R\R-3.2.0\include" /I "C:\Python34\include" /I "C:\Python34\Lib\site-packages\numpy\core\include" /c hello.c 
link /dll /export:main hello.obj Rdll.lib C:/Python34/libs/python34.lib 

जहां Rdll.lib

pexports R.dll > R.exp 
link /lib /def:R.exp /machine:x64 /out:Rdll.lib 
साथ %R_HOME%\bin\x64\R.dll से बनाया गया था के साथ संकलन कर सकते हैं

तो यह आर से इस्तेमाल किया जा सकता:

> dyn.load(paste0("hello", .Platform$dynlib.ext)) 
> .Call("main") 
Hello, 2 worlds 
[1] 1 

जब, हालांकि, मैं यह डेबियन पर

gcc -shared -fPIC -I/usr/share/R/include -I/usr/include/python2.6 -lpython2.6 -L/usr/lib64/R/lib -lR hello.c -o hello.so 

साथ संकलन और आर से निम्न होता है इसे आयात:

> dyn.load("hello.so") 
> .Call("main") 
Traceback (most recent call last): 
    File "/usr/lib/pymodules/python2.6/numpy/__init__.py", line 132, in <module> 
    import add_newdocs 
    File "/usr/lib/pymodules/python2.6/numpy/add_newdocs.py", line 9, in <module> 
    from lib import add_newdoc 
    File "/usr/lib/pymodules/python2.6/numpy/lib/__init__.py", line 4, in <module> 
    from type_check import * 
    File "/usr/lib/pymodules/python2.6/numpy/lib/type_check.py", line 8, in <module> 
    import numpy.core.numeric as _nx 
    File "/usr/lib/pymodules/python2.6/numpy/core/__init__.py", line 5, in <module> 
    import multiarray 
ImportError: /usr/lib/pymodules/python2.6/numpy/core/multiarray.so: undefined symbol: _Py_ZeroStruct 

*** caught segfault *** 
address 0x4, cause 'memory not mapped' 

यह सेगमेंटेशन दोष उत्पन्न करता है जब तक कि numpy से संबंधित सब कुछ टिप्पणी नहीं की जाती है। आर से शुद्ध पायथन के साथ बातचीत करना ठीक लगता है। लेकिन जैसे ही import_array() कहा जाता है वहाँ एक segfault है। मैं -I/usr/share/pyshared/numpy/core/include/ हताशा में जोड़ा गया है और यह कुछ भी नहीं बदला।

अंत में, यदि मैं

gcc -I/usr/share/R/include -I/usr/include/python2.6 -lpython2.6 -L/usr/lib64/R/lib -lR hello.c -o hello 

साथ निम्नलिखित (पिछले करने के लिए समान है, लेकिन हल्के से बदल) कोड

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

int main() { 
    char *localArgs[] = {"R", "--silent"}; 
    Rf_initEmbeddedR(2, localArgs); 
    Py_Initialize(); 
    import_array(); 

    SEXP one = PROTECT(allocVector(INTSXP, 1)); 
    INTEGER(one)[0] = 1; 
    npy_intp dims[1] = {1}; 
    int data[1] = {1}; 
    PyObject *another = PyArray_SimpleNewFromData(1, dims, NPY_INT, data); 

    Rprintf("Hello, %d ", INTEGER(one)[0] + *(int*)PyArray_DATA(another)); 
    PyRun_SimpleString("print('worlds')"); 

    UNPROTECT(1); 
} 

ही डेबियन मशीन पर संकलन और

से कॉल करने की
LD_LIBRARY_PATH=/usr/lib64/R/lib R_HOME=/usr/lib64/R ./hello 

अचानक दुर्घटना नहीं है, अच्छी तरह से काम करता है और अपेक्षा के अनुरूप उत्पादन करता है "हैलो, 2 दुनिया",।

संस्करण हैं: विंडोज: 64 के लिए संकलक संस्करण 19.00.23506, पायथन 3.4.4, numpy 1.9.3, आर 3.2.0 डेबियन: जीसीसी संस्करण 4.4.5 (लक्ष्य: x68_64-linux-gnu) , पायथन 2.6.6, numpy 1.4.1, आर 3.2.1

क्या मैं गलत कर रहा हूँ?

अद्यतन: दोनों जीसीसी और क्लैंग दोनों के साथ पाइथन 3.2 और पायथन 2.7 दोनों के साथ उबंटू पर परीक्षण किया गया। समस्या बरकरार।

उत्तर

0

एक समाधान है कि (इस उदाहरण के साथ वास्तविक कोड के साथ के रूप में भी) काम करता है dlopen साथ libpythonX.Y.so लोड करने के लिए है:

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

#ifndef _WIN32 
#include <dlfcn.h> 
#endif 

SEXP main() { 
#ifndef _WIN32 
    dlopen("libpython2.6.so", RTLD_NOW | RTLD_GLOBAL); 
#endif 
    Py_Initialize(); 
    import_array(); 

    SEXP one = PROTECT(allocVector(INTSXP, 1)); 
    INTEGER(one)[0] = 1; 
    npy_intp dims[1] = {1}; 
    int data[1] = {1}; 
    PyObject *another = PyArray_SimpleNewFromData(1, dims, NPY_INT, data); 

    Rprintf("Hello, %d ", INTEGER(one)[0] + *(int*)PyArray_DATA(another)); 
    PyRun_SimpleString("print('worlds')"); 

    UNPROTECT(1); 
    return one; 
} 

मैं, हालांकि, पूरी तरह से समझ में नहीं आता क्यों यह आवश्यक है ।

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