函数总是返回无意义的值

Posted

技术标签:

【中文标题】函数总是返回无意义的值【英文标题】:Function always returns meaningless value 【发布时间】:2019-12-03 17:16:03 【问题描述】:

我正在编写由 cffi 在 pypy3 中调用的 C 函数。但是,无论真正的返回值是什么,包装函数在 pypy3 中总是返回一个无意义的值。

printf() 函数的输出告诉我在 C 函数中一切正常,但是 pypy3 中的返回值发生了变化。

C函数是这样写的:

double test()
    return 5.12;


double test2()
    double tmp=test();
    printf("!!!!!!!%f\n",tmp);
    return tmp;

cffi构建脚本如下:

from cffi import FFI
ffibuilder = FFI()

ffibuilder.set_source("_faststr_cffi",
                      """
                        #include <Python.h>
                        #include "stdint.h"
                        #include <string.h>
                        typedef uint32_t char32_t;
                      """,
                      sources=['faststr_purec.c']
                      )   # library name, for the linker

ffibuilder.cdef("""
double test();
double test2();
""")

if __name__ == "__main__":
    ffibuilder.compile(verbose=True)

我尝试在 pypy3 控制台中调用 test2():

>>>> from _faststr_cffi import lib
>>>> lib.test2()
!!!!!!!5.120000
16.0

printf 告诉我返回值应该是 5.120000,但它在 pypy3 中返回了 16.0。

我发现了一些线索:如果我在test2() printf函数中改变字符串,pypy3中test2的返回值就会改变。

更新:cpython 3.6.7 中的结果是一样的,所以这不是 pypy3 问题

【问题讨论】:

奇怪的问题,但总是写的字符数吗?因为这就是这里的样子 @EdwardMinnix 确实,这是一个很好的捕获,这导致了错误行为的原因的识别 【参考方案1】:

问题如下:

在这里,您声明函数test()test2()

ffibuilder.cdef("""
double test();
double test2();
""")

这些声明只是为了让 cffi 接口知道要使用的返回值。但是缺少原生 c 函数 test()test2() 的声明。因此,它们被隐式声明返回 int!

现在当函数 test() 从 test2 被调用(隐式声明返回 int)时

double tmp = test();

return tmp;

编译后的代码读取了错误的寄存器(因为它查找的是整数值)并将其转换为双精度值,并将其作为结果返回。碰巧的是,最后一个整数结果是printf() 的结果,它是打印字符串的长度。因此,在您的情况下,您会得到 16 的结果。

解决方法是,正确声明函数 test()test2()

ffibuilder.set_source("_faststr_cffi",
                  """
                    #include <Python.h>
                    #include "stdint.h"
                    #include <string.h>
                    typedef uint32_t char32_t;
                    double test();
                    double test2();
                  """,
                  sources=['faststr_purec.c']
                  )   # library name, for the linker

然后它应该按预期工作。

【讨论】:

我认为你是对的。但是你能解释一下为什么 printf 打印正确的返回值 5.120000 吗? @Jay 这是调用约定的问题。 test() 在寄存器 A 中返回一个 double,但 test2() 在寄存器 B 中查找一个整数,因为 test() 被(隐式)声明返回一个整数。寄存器B中存储的整数是printf()的返回值,在从test()返回之前不会被覆盖。

以上是关于函数总是返回无意义的值的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询返回无意义的结果

Kotlin 函数定义

返回对象和返回引用

为啥函数返回的值总是 null 或 undefined?

无意义的意义

如何将二维数组设置为二维返回[重复]