将C++双指针传递给Python
我可以像下面这样把一维数组传给Python。现在我想知道,能不能通过使用ctypes和numpy把C++的双指针数组传给Python。
test.cpp:
#include <stdio.h>
extern "C" void cfun(const void * indatav, int rowcount, int colcount, void * outdatav);
void cfun(const void * indatav, int rowcount, int colcount, void * outdatav) {
//void cfun(const double * indata, int rowcount, int colcount, double * outdata) {
const double * indata = (double *) indatav;
double * outdata = (double *) outdatav;
int i;
puts("Here we go!");
for (i = 0; i < rowcount * colcount; ++i) {
outdata[i] = indata[i] * 4;
}
puts("Done!");
}
test.py:
import numpy
import ctypes
indata = numpy.ones((5,6), dtype=numpy.double)
outdata = numpy.zeros((5,6), dtype=numpy.double)
lib = ctypes.cdll.LoadLibrary('./ctest.so')
fun = lib.cfun
# Here comes the fool part.
#fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_void_p(outdata.ctypes.data))
fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_int(5), ctypes.c_int(6),
ctypes.c_void_p(outdata.ctypes.data))
print 'indata: %s' % indata
print 'outdata: %s' % outdata
1 个回答
8
这里有一种方法。我没有找到一个很好的方式来在numpy中使用双重乘方(double**)。
test.cpp(Windows系统)
#include <stdio.h>
extern "C" __declspec(dllexport) void cfun(const double ** indata, int rowcount, int colcount, double ** outdata) {
for (int i = 0; i < rowcount; ++i) {
for (int j = 0; j < colcount; ++j) {
outdata[i][j] = indata[i][j] * 4;
}
}
}
test.py
import numpy
import ctypes
# Allocate array of double*
indata = (ctypes.POINTER(ctypes.c_double) * 5)()
for i in range(5):
# Allocate arrays of double
indata[i] = (ctypes.c_double * 6)()
for j in range(6):
indata[i][j] = 1.0
outdata = (ctypes.POINTER(ctypes.c_double) * 5)()
for i in range(5):
outdata[i] = (ctypes.c_double * 6)()
for j in range(6):
outdata[i][j] = 1.0
lib = ctypes.cdll.LoadLibrary('test')
fun = lib.cfun
def dump(a,rows,cols):
for i in range(rows):
for j in range(cols):
print a[i][j],
print
dump(indata,5,6)
fun(ctypes.byref(indata),5,6,ctypes.byref(outdata))
dump(outdata,5,6)
输出结果
1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0
4.0 4.0 4.0 4.0 4.0 4.0
4.0 4.0 4.0 4.0 4.0 4.0
4.0 4.0 4.0 4.0 4.0 4.0
4.0 4.0 4.0 4.0 4.0 4.0
4.0 4.0 4.0 4.0 4.0 4.0