簡體   English   中英

返回雙精度值的 function 值錯誤 (libffi)

[英]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_argffi_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM