【问题标题】:How do call C++ function through Delphi wrapper如何通过Delphi wrapper调用C++函数
【发布时间】:2016-10-24 06:47:07
【问题描述】:

我在这里的第一个问题。如果我做错了,请给我提示。

我的问题:我必须通过 Delphi 包装器 (VCL) 调用 c++ 函数。 delphi 包装器看起来像:

function TFoxBurnerSDK.ReadFileContents(FilePath: string; Offset: int64; var Buffer; Length: integer; var ActualLength: integer): boolean;
begin
    CheckActive;
    if FSessionHandle=nil then begin
        FLastError:=BS_SDK_ERROR_BAD_REQUEST;
        Result:=false;
        Exit;
    end;
    Result:=DLLResult(FoxBurnerSDKCore.ReadFileContents(FSessionHandle,
      PFoxSDKChar(FoxSDKString(FilePath)), Offset, @buffer, Length, @ActualLength));
end

如何从 Delphi 代码中调用此函数。意味着我需要向函数发送什么变量/参数?看来buffer和ActualLength是C++中的指针

int32 BS_CALL ReadFileContents( HSESSION hSession, const TCHAR* lpszFilePath, int64 nOffset, void* pBuffer, int32 nBufferSize, int32* pRead );

这就是我的问题,如何在 Delphi 中处理指针。我认为这是 Delphi 中的正确调用:

procedure TForm1.Button1Click(Sender: TObject);
var Bytes: TBytes;
iRead : integer;
begin
SetLength(Bytes, 2352*27);
iRead:=0;

Burner.ReadFileContents('\autorun.inf', 0, Bytes, 2352*27, iRead);

end; 

但这会导致内存预期。如果我从 C++ 示例中调用该函数,它运行良好。就在德尔福这里,一个期望发生了。所以我觉得我做错了什么。

我希望我提供了所有需要的信息来获得答案。如果没有,请让我知道我想念什么。谢谢。

添加信息:定义:

ReadFileContents : function (Session: HSESSION; FilePath: PFoxSDKChar; Offset: int64; Buffer: pointer; BufferSize: integer; Read: pinteger): integer; stdcall; 

function ReadFileContents(FilePath: string; Offset: int64; var Buffer; Length: integer; var ActualLength: integer): boolean;

【问题讨论】:

  • 你必须向我们展示FoxBurnerSDKCore.ReadFileContents的定义
  • 嗨 AmigoJack,我已在问题中添加了两个定义。
  • 这里没有足够的信息。因此,否决票和关闭投票。请提供有关如何调用该函数的完整描述,并格式化您的代码以便于阅读。
  • 通过H2Pas工具运行C头

标签: c++ delphi delphi-10.1-berlin


【解决方案1】:

应该这样定义:

ReadFileContents: function
( Session: HSESSION  // HSESSION
; FilePath: PChar  // TCHAR*
; Offset: Int64  // int64
; Buffer: Pointer  // void*
; BufferSize: Integer  // int32
; Read: PInteger  // int32*
): Integer;  // int32
cdecl;  // C++, don't know why you use stdcall

调用应该是

var
  iResult, iLength, iRead: Integer;
  sFilePath: String;
  iOffset: Int64;
  aBuf: Array of Byte;
begin
  iLength:= 5;
  SetLength( aBuf, iLength );
  iResult:= ReadFileContents( FSessionHandle, PChar(sFilePath), iOffset, @aBuf[0], iLength, @iRead );

【讨论】:

  • 定义“a”。还编辑了我对完整呼叫示例的回答,因此您不要摆弄我们不知道的类型。
  • 我得到了一个 DLL 版本,其中所有内容都在此函数中进行了注释。所以它只返回一个 0。函数会导致崩溃。那么会不会是C++函数的declare错误呢?
【解决方案2】:

如果FoxBurnerSDKCore 正确定义了 C++ 函数,请注意buffer 参数。对于动态数组Bytes,您必须使用Bytes[0] 作为外部Delphi 函数的参数

(避免使用'pointer to pointer'参数值调用c++函数,因为dyn.array TBytes内部已经是指向数组数据的指针)

【讨论】:

  • 我已在问题中添加了定义。我也尝试了 Bytes[0] 相同的结果。
  • 你用的是什么Delphi版本?如果是 Unicode 之一,请检查 AnsiString 是否为 FilePath
  • 我使用 Rad Studio 10.1
  • 在 10.1 string 参数是 Unicode。尝试更改为AnsiString(没有足够的信息可以清楚地声明这一点)
【解决方案3】:

对不起,这是从C++切换到Delphi的人的问题。经过数小时的调试,我发现函数及其声明未初始化。 我现在添加了:

ReadFileContents:=GetProcAddress(h,'ReadFileContents'); ok:=ok and (@ReadFileContents<>nil);

到包装器中的函数列表,现在一切正常。感谢所有给我答案的人。所有这些答案都非常适合初学者和学习一些东西。再次,非常感谢。

【讨论】:

  • 请注意,如果您向我们展示 MCVE stackoverflow.com/help/mcve,此问题可能会在五分钟内解决
  • 这不是您所提问题的答案。我们无法猜到这一点。当您提出此类问题时,请学习创建 MCVE。
猜你喜欢
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
  • 2015-05-28
  • 2015-08-02
  • 1970-01-01
  • 1970-01-01
  • 2018-07-03
  • 1970-01-01
相关资源
最近更新 更多