ctypes.POINTER(ctypes.c_int) 和 ctypes.c_int * 5 有什么区别?
What's the difference between ctypes.POINTER(ctypes.c_int) and ctypes.c_int * 5?
我正在尝试使用 ctypes 从 C++ 调用 python 函数(回调)。 python 函数接受一个整数数组作为参数。我需要在 python.
中访问这个数组
c代码
typedef void (*FooFunc)(int*, int*);
void runfoo(FooFunc foo_func) {
int dims[5] = {3, 5, 1, 1, 1};
foo_func(dims, dims);
}
python代码
def foo(dims1, dims2):
x = dims1[0]
y = dims1[1]
z = dims1[2]
print(x, y, z)
x = dims2[0]
y = dims2[1]
z = dims2[2]
print(x, y, z)
libc = ctypes.CDLL('./libpath.so')
protofoo = ctypes.CFUNCTYPE(None, ctypes.c_int * 5, ctypes.POINTER(ctypes.c_int))
libc.runfoo(protofoo(foo))
它给
(-333106720, 32766, -333106720)
(3, 5, 1).
原型中的ctypes.c_int * 5和ctypes.POINTER(ctypes.c_int)有什么区别?
ctypes.POINTER(ctypes.int)
等同于 int*
.
ctypes.c_int * 5
是等同于int arr[5]
的类型。它的实现不会像 C 那样退化为指针作为参数,因此当将其用作参数时,它看起来希望数组按堆栈上的值传递。我在下面通过在 C 中以十六进制打印 dims
的地址进行了测试,您可以看到它的 64 位指针值是返回到 python 的前两个 32 位元素,当显示为十六进制时:
test.c
#include <stdio.h>
typedef void (*FooFunc)(int*, int*);
__declspec(dllexport) void runfoo(FooFunc foo_func) {
int dims[5] = {3, 5, 1, 1, 1};
printf("%p\n",dims);
foo_func(dims, dims);
}
test.py
import ctypes
def foo(dims1, dims2):
x = dims1[0]
y = dims1[1]
z = dims1[2]
print(f'{x:08X} {y:08X} {z:08X}')
x = dims2[0]
y = dims2[1]
z = dims2[2]
print(f'{x:08X} {y:08X} {z:08X}')
libc = ctypes.CDLL('test')
protofoo = ctypes.CFUNCTYPE(None, ctypes.c_int * 5, ctypes.POINTER(ctypes.c_int))
libc.runfoo(protofoo(foo))
输出
000000FD6E1EED00
6E1EED00 000000FD 6E1EED00
00000003 00000005 00000001
我正在尝试使用 ctypes 从 C++ 调用 python 函数(回调)。 python 函数接受一个整数数组作为参数。我需要在 python.
中访问这个数组c代码
typedef void (*FooFunc)(int*, int*);
void runfoo(FooFunc foo_func) {
int dims[5] = {3, 5, 1, 1, 1};
foo_func(dims, dims);
}
python代码
def foo(dims1, dims2):
x = dims1[0]
y = dims1[1]
z = dims1[2]
print(x, y, z)
x = dims2[0]
y = dims2[1]
z = dims2[2]
print(x, y, z)
libc = ctypes.CDLL('./libpath.so')
protofoo = ctypes.CFUNCTYPE(None, ctypes.c_int * 5, ctypes.POINTER(ctypes.c_int))
libc.runfoo(protofoo(foo))
它给 (-333106720, 32766, -333106720) (3, 5, 1).
原型中的ctypes.c_int * 5和ctypes.POINTER(ctypes.c_int)有什么区别?
ctypes.POINTER(ctypes.int)
等同于 int*
.
ctypes.c_int * 5
是等同于int arr[5]
的类型。它的实现不会像 C 那样退化为指针作为参数,因此当将其用作参数时,它看起来希望数组按堆栈上的值传递。我在下面通过在 C 中以十六进制打印 dims
的地址进行了测试,您可以看到它的 64 位指针值是返回到 python 的前两个 32 位元素,当显示为十六进制时:
test.c
#include <stdio.h>
typedef void (*FooFunc)(int*, int*);
__declspec(dllexport) void runfoo(FooFunc foo_func) {
int dims[5] = {3, 5, 1, 1, 1};
printf("%p\n",dims);
foo_func(dims, dims);
}
test.py
import ctypes
def foo(dims1, dims2):
x = dims1[0]
y = dims1[1]
z = dims1[2]
print(f'{x:08X} {y:08X} {z:08X}')
x = dims2[0]
y = dims2[1]
z = dims2[2]
print(f'{x:08X} {y:08X} {z:08X}')
libc = ctypes.CDLL('test')
protofoo = ctypes.CFUNCTYPE(None, ctypes.c_int * 5, ctypes.POINTER(ctypes.c_int))
libc.runfoo(protofoo(foo))
输出
000000FD6E1EED00
6E1EED00 000000FD 6E1EED00
00000003 00000005 00000001