【问题标题】:Need help properly calling a C function from Delphi需要帮助从 Delphi 正确调用 C 函数
【发布时间】:2011-08-22 11:44:11
【问题描述】:

我在 Delphi 中静态导入一个动态库 (DLL) 并尝试访问其功能。

这是我试图访问的特定 C 函数减速:

int flann_radius_search_double (flann_index_t index_ptr, /* the index */
                                double* query, /* query point */
                                int* indices, /* array for storing the indices found (will be modified) */
                                double* dists, /* similar, but for storing distances */
                                int max_nn,  /* size of arrays indices and dists */
                                float radius, /* search radius (squared radius for euclidian metric) */
                                struct FLANNParameters* flann_params);

这是我在 Delphi 中的减速:

function flann_radius_search_double(index_ptr: flann_index_t;
  var query: double; var indices: longint; var dists: double;
  max_nn: longint; radius: single; var flann_params: FLANNParameters): longint;
  cdecl; external External_library Name 'flann_radius_search_double';   

我访问了这样的函数:

  type
  TDoubleArray = array[0..1000] of double;
  PDoubleArray = ^TDoubleArray;

  TIntArray = array[0..1000] of Integer;
  PIntArray = ^TIntArray;
  ...
  ... <other unrelated code>

  var      
    Indicies:TIntArray;
    PIndicies:PIntArray;
    Dists:TDoubleArray;
    PDists:PDoubleArray;
    ...
  begin
    ...
    PIndicies:=@Indicies;
    PDists   :=@Dists; 

   radius_s:=flann_radius_search_double(idx ,&PMyArray^[0,0],Pindicies^[0],&PDists^[0],1000,10,&DEFAULT_FLANN_PARAMETERS);

它不工作,看起来很遥远:*( 非常感谢您的帮助!

编辑:我修复了双/单错误,但是当我尝试使用 @Indicies[0] 而不是 Indicies[0] 时出现错误:

错误:通过 var 调用 arg 编号。 3 必须完全匹配:得到“指针” 预期为“LongInt”

【问题讨论】:

  • 您也必须更改进口声明!从 var indices: Integer 更改为 indices: Pinteger,就像我说的和 Rudy 演示的那样。你也必须更改导入声明!从 var 索引更改:整数到索引:Pinteger,就像我说的和 Rudy 演示的那样。

标签: c arrays delphi pointers dll


【解决方案1】:

免责声明:下面写的内容是指问题在完全更改之前的原始版本。在原始版本中,浮点参数都是浮点数。我会敦促 Mike 使用复制/粘贴的方式发布真实代码,以避免浪费人们的时间。

C float 等价于Delphi Single,4 字节浮点类型。这是你遇到的主要问题。

我个人会在导入声明中将数组声明为 PSingle 或 PInteger,而不是使用 var 参数。当通过引用传递单个值时,var 参数是合适的。

调用函数时,我不会使用固定维度的数组。我会使用动态数组和 SetLength。然后使用 PSingle(MyArray) 或 @MyArray[0] 传递数组,无论您喜欢哪个。

我更喜欢 Integer 而不是 Longint,因为我相信 Integer 最接近 C int。

您的数组大小为 1001 个元素,您只需要它们为 1000 个。

结构最好由 var 传递,就像您在导入声明中使用的那样,而不是像您在调用中那样传递。由于您问题中的代码不太匹配,我不想多说。

function flann_radius_search_double(
  index_ptr: flann_index_t;
  var query: Single;
  indices: PInteger;
  dists: PSingle;
  max_nn: Integer;
  radius: Single;
  var flann_params: FLANNParameters
): Integer; cdecl; external External_library Name 'flann_radius_search_double';   
...
var
  indices: array of Integer;
  dists: array of Single;
...
SetLength(indices, 1000);
SetLength(dists, 1000);    
radius_s := flann_radius_search_double(
  idx,
  MyArray[0,0],
  @indicies[0],
  @dists[0],
  1000,
  10.0,
  DEFAULT_FLANN_PARAMETERS
);

【讨论】:

    【解决方案2】:

    在 Delphi 中,float 映射到 Single不是 Double。于是就变成了:

    function flann_radius_search_double(index_ptr: flann_index_t; 
                                        var query: Single;
                                        indices: PInteger; // array, so NOT a var parameter
                                        dists: PSingle;    // array, so NOT a var parameter 
                                        max_nn: Integer;
                                        radius: Single;
                                        var flann_params: FLANNParameters): Integer; 
       cdecl; etc...
    

    你这样称呼它:

     const
       CArraySize = 1000;
    
     ...
    
     var
       Indices: array[0..CArraySize - 1] of Integer;
       Dists: array[0..CArraySize - 1] of Single;
     begin
       ...
       x := flann_radius_search_double(idx, yourQuery, 
              @Indices[0], @Dists[0], Length(Dists), yourRadius, yourFlannParams);
    

    【讨论】:

    • 这里有回声!! ;-)
    • 好吧,他的代码的问题对每个人来说都是一样的。 ;-) 他提到数组的方式完全混乱,所以我决定展示如何正确地做到这一点。一段源代码说了1000多字。 ;-)
    • 嗯,我无法让 @Indicies[0] 或 @Dists[0] 像那样工作......我收到一个错误:错误:由 var 调用 arg no。 3 必须完全匹配:得到“指针”预期“LongInt”
    • @rudy 另一方面,没有解释的源代码除了如何复制之外没有教任何东西。最好将这两个答案合并。
    • @Mike:您是否也应用了其他更改? 我猜你没有。我的翻译使用指针,而不是var 参数。当你想传递数组时,var 参数是错误的(参见我的转换文章)。如果你使用我的翻译,那么你可以像我一样传递数组。
    猜你喜欢
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多