Pythonで出力がnumpy配列であるコードを記述しました。次に、その出力をC++
コードに送信します。ここで、計算の大部分が行われます。実行されました。
Cythonのpublic cdef
を使用してみましたが、いくつかの問題が発生しています。よろしくお願いします!これが私のコードです:
pymodule.pyx
:
from pythonmodule import result # result is my numpy array
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
cdef public void cfunc():
print 'I am in here!!!'
cdef np.ndarray[np.float64_t, ndim=2, mode='c'] res = result
print res
これがcythonizedされたら、私は次のように呼びます。
pymain.c
:
#include <Python.h>
#include <numpy/arrayobject.h>
#include "pymodule.h"
int main() {
Py_Initialize();
initpymodule();
test(2);
Py_Finalize();
}
int test(int a)
{
Py_Initialize();
initpymodule();
cfunc();
return 0;
}
C++
でNameError
変数のresult
を取得しています。ポインタを使って定義し、他の関数から間接的に呼び出しようとしましたが、配列は表示されません。答えは非常に単純だと確信していますが、私にはわかりません。ご協力いただきありがとうございます!
NameErrorは、Pythonがモジュールを見つけることができず、作業ディレクトリが自動的に PYTHONPATH
/に追加されない)という事実が原因でした。 。 setenv
を_C/C++
_コードのsetenv("PYTHONPATH", ".", 1);
とともに使用するとこれが修正されます。
どうやら、これを行う簡単な方法があります。すでに作成された配列を含むpythonモジュール_pythonmodule.py
_の場合:
_import numpy as np
result = np.arange(20, dtype=np.float).reshape((2, 10))
_
public
キーワードを使用して、_pymodule.pyx
_を構造化してその配列をエクスポートできます。いくつかの補助関数を追加することで、通常、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);
_
before_Py_Initialize
_を呼び出すと、Pythonは作業ディレクトリでモジュールを見つけることができます。
残りはかなり簡単です。追加のエラーチェックが必要な場合があり、間違いなく割り当てられたメモリを解放する関数が必要です。
あなたが試みている方法でそれを行うことは、それが価値があるよりもはるかに面倒です、あなたはおそらく _numpy.save
_ を使用して配列をnpy
バイナリファイルに保存し、次にいくつかを使用する方が良いでしょう そのファイルを読み取るC++ライブラリ 。