Ответ 1
Короткий ответ
The NameError был причиной того, что Python не смог найти модуль, рабочий каталог не добавляется автоматически к вашему PYTHONPATH
. Используя setenv
с setenv("PYTHONPATH", ".", 1);
в коде C/C++
, это исправляет.
Более длинный ответ
Там есть простой способ сделать это, по-видимому. С помощью модуля python pythonmodule.py
, содержащего уже созданный массив:
import numpy as np
result = np.arange(20, dtype=np.float).reshape((2, 10))
Вы можете структурировать pymodule.pyx
для экспорта этого массива с помощью ключевого слова public
. Добавляя некоторые вспомогательные функции, вам обычно не нужно прикасаться ни к Python, ни к Numpy C-API
:
from pythonmodule import result
from libc.stdlib cimport malloc
import numpy as np
cimport numpy as np
cdef public np.ndarray getNPArray():
""" Return array from pythonmodule. """
return <np.ndarray>result
cdef public int getShape(np.ndarray arr, int shape):
""" Return Shape of the Array based on shape par value. """
return <int>arr.shape[1] if shape else <int>arr.shape[0]
cdef public void copyData(float *** dst, np.ndarray src):
""" Copy data from src numpy array to dst. """
cdef float **tmp
cdef int i, j, m = src.shape[0], n=src.shape[1];
# Allocate initial pointer
tmp = <float **>malloc(m * sizeof(float *))
if not tmp:
raise MemoryError()
# Allocate rows
for j in range(m):
tmp[j] = <float *>malloc(n * sizeof(float))
if not tmp[j]:
raise MemoryError()
# Copy numpy Array
for i in range(m):
for j in range(n):
tmp[i][j] = src[i, j]
# Assign pointer to dst
dst[0] = tmp
Функция getNPArray
и getShape
возвращает массив и его форму соответственно. copyData
был добавлен, чтобы просто извлечь ndarray.data
и скопировать его, чтобы затем вы могли завершить Python и работать без инициализации интерпретатора.
Пример программы (в C
, C++
должен выглядеть одинаково) будет выглядеть так:
#include <Python.h>
#include "numpy/arrayobject.h"
#include "pyxmod.h"
#include <stdio.h>
void printArray(float **arr, int m, int n);
void getArray(float ***arr, int * m, int * n);
int main(int argc, char **argv){
// Holds data and shapes.
float **data = NULL;
int m, n;
// Gets array and then prints it.
getArray(&data, &m, &n);
printArray(data, m, n);
return 0;
}
void getArray(float ***data, int * m, int * n){
// setenv is important, makes python find
// modules in working directory
setenv("PYTHONPATH", ".", 1);
// Initialize interpreter and module
Py_Initialize();
initpyxmod();
// Use Cython functions.
PyArrayObject *arr = getNPArray();
*m = getShape(arr, 0);
*n = getShape(arr, 1);
copyData(data, arr);
if (data == NULL){ //really redundant.
fprintf(stderr, "Data is NULL\n");
return ;
}
Py_DECREF(arr);
Py_Finalize();
}
void printArray(float **arr, int m, int n){
int i, j;
for(i=0; i < m; i++){
for(j=0; j < n; j++)
printf("%f ", arr[i][j]);
printf("\n");
}
}
Всегда помните, чтобы установить:
setenv("PYTHONPATH", ".", 1);
до вы вызываете Py_Initialize
, чтобы Python мог находить модули в рабочем каталоге.
Остальное довольно прямолинейно. Возможно, потребуется дополнительная проверка ошибок, а определенно нужна функция для освобождения выделенной memmory.
Альтернативный путь без Cython:
Выполнение этого способа, которым вы пытаетесь, является сложной задачей, чем это стоит, вам, вероятно, было бы лучше использовать numpy.save
, чтобы сохранить ваш массив в двоичном файле npy
, а затем используйте некоторую библиотеку С++, которая читает этот файл для вас.