用Delphi中的c dll调用带有数组参数的函数

我在从delphi调用c dll中的函数时遇到问题.

c函数定义如下

BALL_SCRUB_DLL_API int CALLING_CONVENTION bsl2_ModelBallFlight(float cam_X, 
    float cam_Y, 
    float cam_Z, 
    Ball3d* ball_data_in, 
    int n_balls_in, 
    Ball3d* ball_data_out, 
    int &n_balls_out);

球结构如下所示:

  typedef struct 
  { float X;
  float Y;
  float Z;
  float VX;
  float VY;
  float VZ;
  int frame_id;
  int flag;
  } Ball3d;

我想从我的delphi应用程序发送一个ball_data_in数组,c dll将返回相同的数组类型,但在ball_data_out中有修改后的值.

我已经定义了TBall3D记录如下:

TBall3D = record
    X : Single;
    Y : Single;
    Z : Single;
    VX : Single;
    VY : Single;
    VZ : Single;
    Framecount : Integer;
    BallFlag : Integer;
  end;
  PBall3D = ^TBall3D;
  TBall3DArray = array of TBall3D;
  PBall3DArray = ^TBall3DArray;

我的函数declration如下所示:

  TBSL2_ModelBallFlight = function( const Cam_X, Cam_Y, Cam_Z : Single;
                                    const ball_data_in : PBall3DArray;
                                    const NFramesIn : Integer;
                                    var ball_data_out : PBall3DArray;
                                    const NFramesOut : Integer) : Integer; cdecl;

我如何从delphi调用dll?任何帮助将受到高度赞赏.

最佳答案 问题出在这里:

TBall3DArray = array of TBall3D;

那是一个动态数组.这是一种不适合互操作的Delphi数据类型.您可以使用动态数组来保存数据,但不能作为跨互操作边界的参数.在任何情况下,动态数组变量都是指向第一个元素的指针.但是你传递的指针的地址是间接的一个层次太多了.

像这样声明导入:

TBSL2_ModelBallFlight = function(
  Cam_X: Single;
  Cam_Y: Single;
  Cam_Z: Single;
  ball_data_in: PBall3D;
  NFramesIn: Integer;
  ball_data_out: PBall3D;
  var NFramesOut: Integer
): Integer; cdecl;

这是C代码的直接翻译.如果C代码使用Ball3d *(指向Ball3d的指针),则使用PBall3D,一个指向TBall3D的指针.

还要注意最终参数的细微差别.在C代码中,它是int& n_balls_out.这是对int的引用.所以在Delphi中将它设为var参数.

为了调用代码,您可以使用动态数组类型.声明输入和输出数据的变量:

var
  ball_data_in, ball_data_out: TBall3DArray;

您需要通过调用SetLength来初始化数组.然后当你传递参数时,使用@ball_data_in [0]或PBall3D(ball_data_in).同样对于out参数.

我不知道该函数的精确协议,因为原型很少,但调用可能如下所示:

SetLength(ball_data_in, NFramesIn);
SetLength(ball_data_out, NFramesOut);
retval := bsl2_ModelBallFlight(..., PBall3D(ball_data_in), NFramesIn, 
  PBall3D(ball_data_out), NFramesOut);
点赞