Python ctypes 返回值问题

问题描述 投票:0回答:3

为什么我有这个简单的代码

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
或类似的值?谢谢。

python return-value ctypes dynamic-library
3个回答
37
投票

来自文档:

类ctypes.CDLL(名称,模式= DEFAULT_MODE,句柄=无,use_errno = False,use_last_error = False)

此类的实例代表加载的共享库。这些库中的函数使用标准 C 调用约定,并且假定返回 int

简而言之,您将 voidFunct() 定义为返回

int
的函数,而不是 void,并且 Python 期望它返回
int
(无论如何,它得到了 - 它只是碰巧是一个随机值)。

您可能应该做的是明确声明返回值类型

None

dll.voidFunct.restype = None

7
投票

这是未定义的行为。您要求 ctypes 读取根本不存在的返回值。它从堆栈中读取一些内容,但返回的内容是不明确的。


0
投票

以 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 程序并不完全是逐字运行的)

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.