[英]Wrong value with a function that returns a double (libffi)
當 function 返回其值時,從 libffi 返回雙數據類型的 function 似乎未正確轉換,這是我使用的代碼:
#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
的 ffi_arg 類型的參數如果小於sizeof(ffi_arg)
則用於存儲數據,否則它是指向 memory 中數據的指針:
對於非浮點類型,右值必須指向
sizeof(ffi_arg)
或更大的存儲。 對於較小的返回值類型,必須使用ffi_arg
或ffi_sarg
整數類型來保存返回值。
( 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 示例中被忽略了。 給出的示例對我來說非常有效(帶有此警告)。
問題很簡單。 ffi_arg
不是您應該將返回值放入的類型。 相反,第三個參數被定義為指向 void的指針,它應該指向一個足夠大的 object 以包含返回值,並且是正確的 alignment,並且具有正確的類型,或被解釋為這樣,因此:
double rv;
...
ffi_call(&cif, cos, &rv, values);
或者
void *rv = malloc(sizeof (double));
...
ffi_call(&cif, cos, rv, values);
double value = *(double *)rv;
至於警告,這是因為 libffi 代碼不是嚴格可移植的。 function 指針無法自動轉換為void *
。 您可以使用顯式強制轉換使警告靜音:
ffi_call(&cif, (void *)cos, rv, values);
至少它不會使它比現在更錯誤。
編輯 - 根據文檔
FFI - 對於非浮點類型,右值必須指向 sizeof(ffi_arg) 或更大的存儲。 對於較小的返回值類型,必須使用 ffi_arg 或 ffi_sarg 整數類型來保存返回值。
ffi_call 的 function 定義是
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
而不是將 ffi_arg 傳遞給 function 您需要傳遞一個分配了雙精度空間的 void*。
void* rc = malloc(sizeof(double));
ffi_call(&cif, cos, rc, values);
printf("%f\n", *(double *)rc);
這將導致正確的答案,而無需您對被調用的 function 做出任何假設。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.