returns double (libffi) 函数的错误值
Wrong value with a function that returns a double (libffi)
当函数 returns 其值时,似乎从 libffi 返回双精度数据类型的函数未正确转换,这是我使用的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ffi.h>
#include <math.h> // The make call the function `cos` by the FFI.
int main()
{
ffi_cif cif;
ffi_type *args[1];
void *values[1];
ffi_arg rc;
args[0] = &ffi_type_double;
void *ptr = malloc(sizeof(double));
*((double *)ptr) = 3.0;
values[0] = ptr;
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_double, args) == FFI_OK)
ffi_call(&cif, cos, &rc, values);
printf("%f\n", (double)rc);
return 0;
}
结果如下:13830464316077631000.000000
.
ffi_arg
类型是 unsigned long long
的别名。文档指出传递给 ffi_call
函数的 ffi_arg
类型的参数,如果小于 sizeof(ffi_arg)
则用于存储数据,否则它是指向内存中数据的指针:
rvalue must point to storage that is sizeof(ffi_arg)
or larger for
non-floating point types. For smaller-sized return value types, the
ffi_arg
or ffi_sarg
integral type must be used to hold the return
value.
(https://manpages.debian.org/testing/libffi-dev/ffi_call.3.en.html)
所以我用指针解引用试了一下:
void* rc;
// The code to call the function and initialize the CIF...
double my_value = *(double *)((void *)rc);
导致程序崩溃。
我应该如何访问使用 rc
变量存储的值?
编辑 1
用于编译程序的命令行:
gcc source.c -lffi -o source
编译时没有错误或警告。
编辑 2
添加“-Wall”构建选项后,我得到:
warning: passing argument 2 of 'ffi_call' from incompatible pointer type [-Wincompatible-pointer-types]
ffi_call(&cif, cos, &rc, values);
^~~
这个警告似乎在 libffi example 中被忽略了。给出的示例对我来说非常有效(带有此警告)。
编辑 -
根据文档
FFI -
rvalue must point to storage that is sizeof(ffi_arg) or larger for non-floating point types. For smaller-sized return value types, the ffi_arg or ffi_sarg integral type must be used to hold the return value.
ffi_call 的函数定义是
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
无需将 ffi_arg 传递给函数,您需要传递分配给 space 双精度值的 void*。
void* rc = malloc(sizeof(double));
ffi_call(&cif, cos, rc, values);
printf("%f\n", *(double *)rc);
这将导致正确的答案,而无需您对被调用的函数做出任何假设。
问题简单。 ffi_arg
不是您应该将 return 值放入的类型。相反,第三个参数被定义为一个 指向 void 的指针,它应该指向一个 适当大 的对象以包含 return 值,并且正确对齐,并且 正确类型 ,或者这样解释,因此:
double rv;
...
ffi_call(&cif, cos, &rv, values);
或
void *rv = malloc(sizeof (double));
...
ffi_call(&cif, cos, rv, values);
double value = *(double *)rv;
至于警告,这是因为 libffi 代码不是严格可移植的。函数指针不能自动转换为 void *
。您可以通过显式强制转换使警告静音:
ffi_call(&cif, (void *)cos, rv, values);
至少它不会使它比现在更加错误。
当函数 returns 其值时,似乎从 libffi 返回双精度数据类型的函数未正确转换,这是我使用的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ffi.h>
#include <math.h> // The make call the function `cos` by the FFI.
int main()
{
ffi_cif cif;
ffi_type *args[1];
void *values[1];
ffi_arg rc;
args[0] = &ffi_type_double;
void *ptr = malloc(sizeof(double));
*((double *)ptr) = 3.0;
values[0] = ptr;
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_double, args) == FFI_OK)
ffi_call(&cif, cos, &rc, values);
printf("%f\n", (double)rc);
return 0;
}
结果如下:13830464316077631000.000000
.
ffi_arg
类型是 unsigned long long
的别名。文档指出传递给 ffi_call
函数的 ffi_arg
类型的参数,如果小于 sizeof(ffi_arg)
则用于存储数据,否则它是指向内存中数据的指针:
rvalue must point to storage that is
sizeof(ffi_arg)
or larger for non-floating point types. For smaller-sized return value types, theffi_arg
orffi_sarg
integral type must be used to hold the return value.
(https://manpages.debian.org/testing/libffi-dev/ffi_call.3.en.html)
所以我用指针解引用试了一下:
void* rc;
// The code to call the function and initialize the CIF...
double my_value = *(double *)((void *)rc);
导致程序崩溃。
我应该如何访问使用 rc
变量存储的值?
编辑 1
用于编译程序的命令行:
gcc source.c -lffi -o source
编译时没有错误或警告。
编辑 2
添加“-Wall”构建选项后,我得到:
warning: passing argument 2 of 'ffi_call' from incompatible pointer type [-Wincompatible-pointer-types]
ffi_call(&cif, cos, &rc, values);
^~~
这个警告似乎在 libffi example 中被忽略了。给出的示例对我来说非常有效(带有此警告)。
编辑 - 根据文档
FFI - rvalue must point to storage that is sizeof(ffi_arg) or larger for non-floating point types. For smaller-sized return value types, the ffi_arg or ffi_sarg integral type must be used to hold the return value.
ffi_call 的函数定义是
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
无需将 ffi_arg 传递给函数,您需要传递分配给 space 双精度值的 void*。
void* rc = malloc(sizeof(double));
ffi_call(&cif, cos, rc, values);
printf("%f\n", *(double *)rc);
这将导致正确的答案,而无需您对被调用的函数做出任何假设。
问题简单。 ffi_arg
不是您应该将 return 值放入的类型。相反,第三个参数被定义为一个 指向 void 的指针,它应该指向一个 适当大 的对象以包含 return 值,并且正确对齐,并且 正确类型 ,或者这样解释,因此:
double rv;
...
ffi_call(&cif, cos, &rv, values);
或
void *rv = malloc(sizeof (double));
...
ffi_call(&cif, cos, rv, values);
double value = *(double *)rv;
至于警告,这是因为 libffi 代码不是严格可移植的。函数指针不能自动转换为 void *
。您可以通过显式强制转换使警告静音:
ffi_call(&cif, (void *)cos, rv, values);
至少它不会使它比现在更加错误。