[英]How to pass a struct from python to a ctypes function in a shared object?
I'm trying to create something similar to numpy to learn how ctypes work and I ran into a problem with passing a pointer to a "Matrix" struct to some functions.我正在尝试创建类似于 numpy 的东西来了解 ctypes 的工作原理,但在将指向“Matrix”结构的指针传递给某些函数时遇到了问题。
The output of calling print_matrix would always be some random integer and then a few spaces.调用 print_matrix 的 output 总是一些随机的 integer 然后是几个空格。
I'm using Python 3.7.5 and the C code was compiled using: gcc -shared -o libarray.so -fPIC array.c I'm using Python 3.7.5 and the C code was compiled using: gcc -shared -o libarray.so -fPIC array.c
C Code: C 代码:
typedef struct Matrix {
int *arr;
int *shape;
int dims;
} Matrix;
void print_matrix(Matrix *Mat) {
int num = 1;
for (int i = 0; i < Mat -> dims; i++) {num *= Mat -> shape[i];}
for (int i = 0; i < num; i++) {
printf("%d ", Mat -> arr[i]);
if (Mat -> dims >= 2) {
if (((i + 1) % Mat -> shape[0]) == 0) {
printf("\n");
}
}
}
}
Python Code: Python 代码:
import ctypes as cty
class Matrix(cty.Structure):
_fields_ = [("arr", cty.POINTER(cty.c_int)), ("shape", cty.POINTER(cty.c_int)), ("dims", cty.c_int)]
libarray = cty.CDLL("./libarray.so")
print_matrix = libarray.print_matrix
print_matrix.restype = None
print_matrix.argtypes = [Matrix]
mat = Matrix((cty.c_int * 4)(*[1, 2, 3, 4]), (cty.c_int * 2)(*[2, 2]), cty.c_int(2))
print_matrix(mat)
I know that for this function, I can just pass the Matrix struct directly by change the print_matrix code, but because of some other things in my code, I want to deal mostly with pointers.我知道对于这个 function,我可以通过更改 print_matrix 代码直接传递 Matrix 结构,但是由于我的代码中的一些其他内容,我想主要处理指针。 Sorry for this weird restriction and thanks in advance.
很抱歉这个奇怪的限制,并提前感谢。
The problem is that in C, you have void print_matrix(Matrix *Mat)
, but in Python, you have print_matrix.argtypes = [Matrix]
.问题是在 C 中,您有
void print_matrix(Matrix *Mat)
,但在 Python 中,您有print_matrix.argtypes = [Matrix]
。 Python is passing a Matrix
, but C is expecting a Matrix *
. Python 正在传递一个
Matrix
,但 C 期待一个Matrix *
。 It doesn't matter which one you use, but they have to agree.你使用哪一个并不重要,但他们必须同意。
If you want to pass a Matrix
, then leave your Python code alone and change your C code to this:如果你想传递一个
Matrix
,那么留下你的 Python 代码并将你的 C 代码更改为:
#include <stdio.h>
typedef struct Matrix {
int *arr;
int *shape;
int dims;
} Matrix;
void print_matrix(Matrix Mat) {
int num = 1;
for (int i = 0; i < Mat.dims; i++) {num *= Mat.shape[i];}
for (int i = 0; i < num; i++) {
printf("%d ", Mat.arr[i]);
if (Mat.dims >= 2) {
if (((i + 1) % Mat.shape[0]) == 0) {
printf("\n");
}
}
}
}
I changed Matrix *Mat
to Matrix Mat
and ->
to .
我将
Matrix *Mat
更改为Matrix Mat
并将->
更改为.
. .
If you want to pass a Matrix *
, then leave your C code alone and change your Python code to this:如果你想传递一个
Matrix *
,那么留下你的 C 代码并将你的 Python 代码更改为:
import ctypes as cty
class Matrix(cty.Structure):
_fields_ = [("arr", cty.POINTER(cty.c_int)), ("shape", cty.POINTER(cty.c_int)), ("dims", cty.c_int)]
libarray = cty.CDLL("./libarray.so")
print_matrix = libarray.print_matrix
print_matrix.restype = None
print_matrix.argtypes = [cty.POINTER(Matrix)]
mat = Matrix((cty.c_int * 4)(*[1, 2, 3, 4]), (cty.c_int * 2)(*[2, 2]), cty.c_int(2))
print_matrix(cty.byref(mat))
I changed [Matrix]
to [cty.POINTER(Matrix)]
and mat
to cty.byref(mat)
.我将
[Matrix]
更改为[cty.POINTER(Matrix)]
并将mat
更改为cty.byref(mat)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.