Liang An
Liang An

Reputation: 61

import_array() error while embedding python and numpy to C++

I write a simple code trying to use numpy in C++. My OS is ubuntu16.04, with gcc5.4.0, Python2.7.12 and numpy1.15.0. Here is my codetest2.cpp:

#include "Python.h"
#include "numpy/arrayobject.h"

int main(int argc, char **argv) 
{
    Py_Initialize();     
    import_array(); 

    Py_Finalize(); 
    return 0; 
}

I use a CMakeLists.txt like this:

cmake_minimum_required(VERSION 3.10) 

project(test_python LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE DEBUG)

set(PYTHON_INCLUDE_PATH /usr/include/python2.7)
set(PYTHON_LIBRARY /usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so)
set(NUMPY_INCLUDE_PATH /usr/local/lib/python2.7/dist-packages/numpy/core/include)

include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${NUMPY_INCLUDE_PATH})

add_executable(test_python test2.cpp) 
target_link_libraries(test_python 
    ${PYTHON_LIBRARY}
)

But while I make it, I come up with following compiling error:

/usr/local/lib/python2.7/dist-packages/numpy/core/include/numpy/__multiarray_api.h:1547:144: error: return-statement with no value, in function returning ‘int’ [-fpermissive]
 #define import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return NUMPY_IMPORT_ARRAY_RETVAL; } }
                                                                                                                                                ^
/home/camsys/projects/hmr_c/test/test2.cpp:7:5: note: in expansion of macro ‘import_array’
     import_array(); 
     ^

This is weird, because when I use Python3.5 with Numpy1.15.0, everything is ok. Could any one tell me why this error happened and how to solve it?

And I found another similar question asked 4 years ago with no answer Passing C++ array to python. That question was about python3.4, while I am dealing with python2.7.

Upvotes: 6

Views: 3268

Answers (1)

saqib1707
saqib1707

Reputation: 51

import_array() is a macro defined inside /usr/local/lib/pythonX.Y/dist-packages/numpy/core/include/numpy/__multiarray_api.h. During code pre-processing (before compilation), the definition of this macro is expanded and replaced in the main function just like this:

int main(int argc, char **argv) 
{
    Py_Initialize();     
    {
        if (_import_array() < 0) {
            PyErr_Print();
            PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
            return NUMPY_IMPORT_ARRAY_RETVAL;
        }
    }
    Py_Finalize(); 
    return 0; 
}

Now, NUMPY_IMPORT_ARRAY_RETVAL is also a macro defined inside the same file __multiarray_api.h. This macro is defined as NULL for python3 and above, otherwise nothing.

#if PY_VERSION_HEX >= 0x03000000
#define NUMPY_IMPORT_ARRAY_RETVAL NULL
#else
#define NUMPY_IMPORT_ARRAY_RETVAL
#endif

The int main function is supposed to return an integer, but inside the expanded if statement (if the condition _import_array() < 0 is met), it returns either NULL = 0 (#define NULL 0) for python versions >= 3, therefore it works. For python versions < 3, the main function returns nothing, hence the error.

Workaround (for python versions < 3):

void temp_func() {
    import_array();
}

int main(int argc, char **argv) {
    Py_Initialize();     
    temp_func();

    Py_Finalize(); 
    return 0; 
}

Hope, this answers the question.

Upvotes: 2

Related Questions