【问题标题】:Translate C++ to Delphi, or convert to a dll [closed]将 C++ 转换为 Delphi,或转换为 dll [关闭]
【发布时间】:2013-12-17 12:57:51
【问题描述】:

我正在尝试通过 Delphi 中的 USB 端口连接到 Graphtec 绘图仪。以下 C++ 代码片段由制造商提供:

#include <windows.h>
#include <stdio.h>

typedef HANDLE (APIENTRY *PROC_GITK_OPENUSB)(int, int, DWORD);

int main(int argc, char* argv[])
{
    HMODULE hUsbLib = LoadLibrary("GITKUSBP.DLL");

    PROC_GETK_OPENUSB lpfnGITK_OpenUsb = (PROC_GITK_OPENUSB)GetProcAddress(hUsbLib,            "GITK_OpenUsb");

    HANDLE hWrite = (lpgnGITK_OpenUsb)(0, 0, FILE_FLAG_OVERLAPPED);
    HANDLE hRead  = (lpgnGITK_OpenUsb)(0, 1, FILE_FLAG_OVERLAPPED);

    OVERLAPPED WriteEvt, ReadEvt;
}

当然还有更多,但这似乎是关键代码。在 Delphi 中,我尝试翻译并不成功。我需要一些翻译方面的专业知识,或者需要一些关于将 C++ 代码转换为我可以从 Delphi 调用的 dll 的指导。

【问题讨论】:

  • 尝试过 h2pas 进行类型转换?

标签: c++ delphi dll language-translation


【解决方案1】:

您不需要将 C++ 代码编译成 DLL。您已经有了一个包含代码的 DLL——GITKUSBP.DLL。你没有的是一种从你的 Delphi 代码链接到它的方法。

在 C++ 中,您通常使用头文件 (.h) 和导入库 (.lib) 进行链接。尽管此处的示例使用运行时链接,并且碰巧实现它的效果很差。它根本不执行错误检查。我不会认为 C++ 代码是一个很好的例子。

在 Delphi 中,您需要将头文件转换为 Pascal。它可能看起来像这样:

function GITK_OpenUsb(
  param1: Integer; 
  param2: Integer;
  param3: DWORD
): THandle; stdcall; external 'GITKUSBP.DLL';

您可以从库的文档中找到更有意义的参数名称。

stdcall 的调用约定来自 C++ 代码中的APIENTRY。这是WINAPI 的宏,其计算结果为__stdcall

仅此而已。您现在可以像这样从您的 Delphi 代码中调用该函数:

var
  hWrite, hRead: THandle;
....
hWrite := GITK_OpenUsb(0, 0, FILE_FLAG_OVERLAPPED);
hRead := GITK_OpenUsb(0, 1, FILE_FLAG_OVERLAPPED);

我在这里使用了加载时间链接。这总是更加方便和清洁。它免除了您编写样板来加载库、导入函数和执行错误检查的需要。因此,如果可以,请选择使用加载时间链接。

毫无疑问,还有更多功能需要转换。您必须以类似的方式进行操作。一定要利用现有资源来学习。

  • 您当然必须阅读 Delphi 文档:Importing Functions from Libraries
  • 标题翻译的重要来源是 Delphi 中的 Windows 单元。
  • JEDI 项目有很多标题翻译。
  • 当然,Stack Overflow 上有大量关于此主题的问题。

【讨论】:

  • 哇!谢谢你,大卫,快速而详细的回复。你摇滚!我会接受你的建议。
【解决方案2】:

那么你在 Delphi 中的代码 sn-p 是:


更新:我改进了 sn-p 以处理 DLL 加载错误:

uses Windows;

type
  TPROC_GITK_OPENUSB = function(A1, A2: Integer; A3: DWORD): THandle; stdcall;

procedure main;
var
  hUsbLib: THandle;
  fnGITK_OpenUsb: TPROC_GITK_OPENUSB;
  hWrite, hRead: THandle;
  WriteEvt, ReadEvt: OVERLAPPED;

begin
  hUsbLib:= LoadLibrary('GITKUSBP.DLL');
  if (hUsbLib <> 0) then begin
    @fnGITK_OpenUsb:= GetProcAddress(hUsbLib, 'GITK_OpenUsb');
    if @fnGITK_OpenUsb <> nil then begin
      hWrite:= fnGITK_OpenUsb(0, 0, FILE_FLAG_OVERLAPPED);
      hRead:= fnGITK_OpenUsb(0, 1, FILE_FLAG_OVERLAPPED);
// ....    
    end;
    FreeLibrary(hUsbLib);
  end;
end;

begin
  main;
end.

【讨论】:

  • 这是一个出色的翻译,但它的缺点是您还翻译了缺乏错误处理! ;-)
  • 我只回答被问到的问题:)。 sn-p 本身也没有任何意义,只能作为更大代码的一部分。
  • 好吧,警告提问者并没有什么坏处,尤其是因为他们似乎没有意识到这些问题。如果您添加了这样的警告,我不会觉得有必要用 cmets 混淆您的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
  • 2016-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多