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

时间:2013-11-28 19:50:46

标签: c++ arrays delphi 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;

我的功能解除如下:

  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?任何帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:2)

问题在于:

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);