为什么我有这个简单的代码
void voidFunct() {
printf("voidFunct called!!!\n");
}
我将其编译为动态库
gcc -c LSB.c -o LSB.o
gcc -shared -Wl -o libLSB.so.1 LSB.o
我使用 ctypes 从 python 解释器调用函数
>>> from ctypes import *
>>> dll = CDLL("./libLSB.so.1")
>>> return = dll.voidFunct()
voidFunct called!!!
>>> print return
17
为什么从
void
方法返回的值是 17
而不是 None
或类似的值?谢谢。
来自文档:
类ctypes.CDLL(名称,模式= DEFAULT_MODE,句柄=无,use_errno = False,use_last_error = False)此类的实例代表加载的共享库。这些库中的函数使用标准 C 调用约定,并且假定返回 int。
简而言之,您将 voidFunct() 定义为返回
int
的函数,而不是 void,并且 Python 期望它返回 int
(无论如何,它得到了 - 它只是碰巧是一个随机值)。
您可能应该做的是明确声明返回值类型
None
。
dll.voidFunct.restype = None
这是未定义的行为。您要求 ctypes 读取根本不存在的返回值。它从堆栈中读取一些内容,但返回的内容是不明确的。
以 Boaz Yaniv 的答案为基础:
===引用===
简而言之,您将
voidFunct()
定义为返回 int
的函数,而不是 void
,并且 Python 希望它返回 int
。
...
您可能应该做的是明确声明返回值类型 None
:
dll.voidFunct.restype = None
===取消引用===
如果研究一下 C 的内部结构,就会发现整数返回值是通过 ax/eax 寄存器返回给调用者的,而不是通过堆栈或类似的方式。所以打印出来的值并不完全是随机的,而是函数返回时恰好在 ax 寄存器中的值。
在这种情况下,最近使用的 ax/eax 寄存器是 printf() 语句的(未使用的)返回值 - 这是 printf() 函数写入控制台的字节数。 (注意字符串“voidFunct called!!!”的长度 “是 20,而不是 17。我们可以相当肯定,上面提到的 C 程序并不完全是逐字运行的)