将C ++翻译为Delphi,或转换为dll

时间:2013-12-17 12:57:51

标签: c++ delphi dll language-translation

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

#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的一些指导。

2 个答案:

答案 0 :(得分:5)

您无需将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上有关于此主题的大量问题。

答案 1 :(得分:3)

Delphi中的代码片段是:


更新:我改进了代码片段来处理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.