0

我正在尝试通过 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 的指导。

4

2 回答 2

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来自APIENTRYC++ 代码中的 。这是一个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
  • 标题翻译的一个重要来源是WindowsDelphi 中的单元。
  • JEDI 项目有很多标题翻译。
  • 当然,在 Stack Overflow 上有很多关于这个主题的问题。
于 2013-12-17T13:32:44.917 回答
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.
于 2013-12-17T13:33:47.687 回答