我的目标是C编写结构成员,然后将结构指针传递回python。该结构包含2个相同大小的双精度数组(分别代表实零件和imag零件数据),数组中的行数,列数。由于它在Python中是行主要的,因此我可以通过POINTER(double)类型传递2d数组,并且在给定row&col的情况下,我可以访问正确的位置。 (而不是POINTER(POINTER(c_double)))
在Python中
class tx_data(Structure):
_fields_=[("I", POINTER(c_double)), ("m", c_int), ("n", c_int), ("Q", POINTER(c_double))]
# argtypes& restype for preventing invalid data
writereturn = lib.WriteReturn
writei= lib.WriteI
writereturn.argtypes = [c_int,c_int]
writereturn.restype=POINTER(tx_data)
writei.argtypes = [c_int,c_int,POINTER(tx_data)]
writei.restype= None
WriteI函数将结构实例与零填充数据一起传递,我希望数组由C填充数据。但是,数据没有改变。我不确定是否无法传递结构的指针,并且该结构也包含指向double的指针
def WriteI(Nrow, len):
txData_pointer = POINTER(tx_data)
rec_data = tx_data()
I = np.zeros((Nrow,len), dtype=np.double)
Q = np.zeros((Nrow,len), dtype=np.double)
rec_data.I = I.ctypes.data_as(POINTER(c_double))
rec_data.Q = Q.ctypes.data_as(POINTER(c_double))
rec_data.m = c_int(Nrow)
rec_data.n = c_int(len)
print(addressof(rec_data))
print(txData_pointer.from_address(addressof(rec_data)))
print("in PY--m:%d, n:%d"%(Nrow,len))
writei(Nrow, len, txData_pointer.from_address(addressof(rec_data)))
#rx(Nrow, len, byref(rec_data))
return rec_data
然后,我看到了另一篇文章,通过POINTER(structure)返回了写入数据。我尝试如下操作,但弹出OSError:exception:Access Conflict Writing 0x0000000000000000
def WriteReturn(Nrow, len):
rec_data = tx_data.from_address(writereturn(Nrow, len))
xk = tx_data()
xk.I = cast(rec_data.contents.I, POINTER(c_double))
xk.Q = cast(rec_data.contents.Q, POINTER(c_double))
xk.m = c_int(Nrow)
xk.n = c_int(len)
return xk
在Header.h中
typedef struct{
double *I;
int m;
int n;
double *Q;
}tx_data;
extern "C" __declspec(dllexport) void WriteI(int Nrow, int len, tx_data &xk);
extern "C" __declspec(dllexport) tx_data* WriteReturn(int Nrow, int len);
在C ++中
void WriteI(int Nrow, int len, tx_data &xk) {
size_t t;
for (int i = 0; i < Nrow; i++) {
for (int j = 0; j < len; j++) {
t = len * i + j;
xk.I[t] = 0.3+t;
xk.Q[t] = 0.7+t;
}
}
}
tx_data* WriteReturn(int Nrow, int len) {
tx_data* xk = new tx_data();
size_t t;
xk->m = Nrow;
xk->n = len;
for (int i = 0; i < Nrow; i++) {
for (int j = 0; j < len; j++) {
t = len * i + j;
xk->I[t] = 0.3 + t;
xk->Q[t] = 0.7 + t;
}
}
return xk;
}
有人可以阐明一些解决方法吗?
这里有很多问题。
首先,txData_pointer.from_address(addressof(rec_data))
错误。这基本上是*(tx_data **)&rec_data
的C等效项,这显然是错误的,因为rec_data
不是指针。如果您想无缘无故地变得复杂,请改为执行tx_data.from_address(addressof(rec_data))
,但是如果您想变得简单,则只需执行byref(rec_data)
。
此后,tx_data.from_address(writereturn(Nrow, len))
错误。此处无需涉及from_address
;只需保存writereturn
的结果即可。
接下来,void WriteI(int Nrow, int len, tx_data &xk)
错误。您不能在要声明&
的函数签名中使用extern "C"
。使用*
代替&
,然后将WriteI
更改为使用xk->
代替xk.
。
最后,在WriteReturn
中,您正在创建一个新的tx_data
,但没有尝试为其分配I
或Q
。您需要执行xk->I = new double[Nrow * len];
,对于Q
也是如此。
固定所有这些后,您的代码即可正常工作。这里是修复程序(Python中的class
可以保持不变,所以我没有重新发布它):
def WriteI(Nrow, len):
rec_data = tx_data()
I = np.zeros((Nrow,len), dtype=np.double)
Q = np.zeros((Nrow,len), dtype=np.double)
rec_data.I = I.ctypes.data_as(POINTER(c_double))
rec_data.Q = Q.ctypes.data_as(POINTER(c_double))
rec_data.m = c_int(Nrow)
rec_data.n = c_int(len)
print(addressof(rec_data))
print("in PY--m:%d, n:%d"%(Nrow,len))
writei(Nrow, len, byref(rec_data))
#rx(Nrow, len, byref(rec_data))
return rec_data
def WriteReturn(Nrow, len):
rec_data = writereturn(Nrow, len)
xk = tx_data()
xk.I = cast(rec_data.contents.I, POINTER(c_double))
xk.Q = cast(rec_data.contents.Q, POINTER(c_double))
xk.m = c_int(Nrow)
xk.n = c_int(len)
return xk
typedef struct{
double *I;
int m;
int n;
double *Q;
}tx_data;
extern "C" __declspec(dllexport) void WriteI(int Nrow, int len, tx_data *xk);
extern "C" __declspec(dllexport) tx_data* WriteReturn(int Nrow, int len);
void WriteI(int Nrow, int len, tx_data *xk) {
size_t t;
for (int i = 0; i < Nrow; i++) {
for (int j = 0; j < len; j++) {
t = len * i + j;
xk->I[t] = 0.3+t;
xk->Q[t] = 0.7+t;
}
}
}
tx_data* WriteReturn(int Nrow, int len) {
tx_data* xk = new tx_data();
size_t t;
xk->I = new double[Nrow * len];
xk->m = Nrow;
xk->n = len;
xk->Q = new double[Nrow * len];
for (int i = 0; i < Nrow; i++) {
for (int j = 0; j < len; j++) {
t = len * i + j;
xk->I[t] = 0.3 + t;
xk->Q[t] = 0.7 + t;
}
}
return xk;
}
顺便说一下,您可以做很多事情来改进这段我没有讲过的代码。这只是使其正常工作所需的最低限度的更改。