【问题标题】:Calling delphi procedure from C++从 C++ 调用 delphi 过程
【发布时间】:2021-07-15 00:57:21
【问题描述】:

我有一个用 Delphi 编写的 DLL,我需要从 C++ 代码中调用它。 Delphi中程序的签名是:

procedure GetDeviceName(     No: integer;
                           Name: PChar;
                            Len: integer;
                      var Error: integer); stdcall;

从 DLL 的代码中,我相信我可以用这段代码来调用它:

typedef void (__stdcall *GetDeviceNamePtr)(int, char*, int, int*);

GetDeviceNamePtr GetDeviceName = (GetDeviceNamePtr) GetProcAddress(m, "GetDeviceName");

char DeviceName[256];
int Error;
GetDeviceName(1, DeviceName, 256, &Error);

但是,我遇到了访问冲突。过程签名的最后一个参数应该是指向整数还是整数的指针?我对过程声明中的“var”关键字感到困惑。我检查了 DLL 的导出符号,并且考虑的过程已正确导出。我的程序出了什么问题?

更多关于环境的信息:

  1. 这是一个用 delphi 6 编译的 dll。
  2. 仅限 ANSI。
  3. 我在 C++ 端调试,异常就在函数调用上。
  4. 调用 DLL API 的函数没有返回任何内容。

【问题讨论】:

  • 对我来说第一个明显的测试是提供一个足够大的数组(256 字节),但只告诉 128(甚至只有 64)作为长度参数,然后查看写入它的内容。
  • 显示的代码对我来说看起来不错。 AccessViolation 错误消息实际上逐字逐句地说了什么?您是否确认 GetProcAddress() 没有返回 NULL 指针? DLL 中的代码是什么样的?请编辑您的问题以提供更多详细信息。
  • 您可以使用 Delphi 调试您的 DLL: 在 DLL 项目中,将“主机应用程序”设置为您的 C++ 应用程序。在你的函数中放置一个断点并运行。 Delphi 将加载 C++ 应用程序,然后再加载 DLL。然后 Delphi 调试器将在 DLL 中的断点处停止,从那里您可以单步执行 Delphi 代码以了解问题所在。

标签: c++ delphi


【解决方案1】:

从您提供的相当少量的信息来看,我最初的想法是您已将数组 DeviceName 声明为局部变量,因此它在堆栈上,然后在您尝试时溢出堆栈给您一个 AV返回。

  • 在现代版本的 Delphi 中,Charwchar_tPCharwchar_t*(所以 256 的 Len 可能意味着 256 个字节或 128 个字符)。

  • 原型中的var表示通过引用传递的参数,所以我希望int*

  • 您是否检查过编写 DLL 的 Delphi 版本和调用应用程序中的可变大小?如果他们认为 Integerint 的大小不同(32 位与 64 位),那么您的指针将是垃圾。

  • 您能否在调试器中单步执行 DLL?如果您可以查看当您进入例程时变量是如何分配的,该例程应该确定您是否通过了它的预期。

  • 最后,您确定 Delphi DLL 确实有效吗? (我之前就被这件事抓住了,你可以花几天时间做一些不是你问题的事情!)

【讨论】:

  • 从技术上讲,var Error: integer 在 C++ 中会翻译为 int &Error。但是int *Error 也可以工作(这是 C 需要使用的)。但无论如何,Delphi 和 C++ 都使用 32 位来表示 Integer/int 的大小,分别
  • 我在增加缓冲区大小时遇到​​了同样的异常。我希望您回答的最后一点会出现问题:Rob Lambden
  • @rbw 那么问题必须在 DLL 本身内部,但您尚未显示该代码。请编辑您的问题以添加它。
猜你喜欢
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多