使用指针调用 C++ DLL 函数

Posted

技术标签:

【中文标题】使用指针调用 C++ DLL 函数【英文标题】:Calling C++ DLL function with pointer 【发布时间】:2019-07-18 16:27:53 【问题描述】:

尝试从 VBA (MS Access) 调用 C++ DLL 并不断收到“错误的 dll 调用约定”错误,以及 MS Access 崩溃。

这是我试图调用的 C++ API 函数:

_IMPORT HRESULT _CONVENTION PCRSNewTrip (Trip *pTripID);

“行程”定义为:

typedef long Trip;

来自 API 标头:

#if defined (__BORLANDC__) 
#define  _IMPORT __declspec( dllimport )
#define  _CONVENTION __stdcall
#elif defined (_MSC_VER)
#define  _IMPORT _declspec( dllimport )
#define  _CONVENTION _cdecl
#endif

这里有一些关于函数的信息: PCRSNewTrip() 在传入的指针参数 (tripID) 中放置新行程的句柄。返回代码与所有其他 DLL 函数(用于错误处理)相同。

这是我调用该函数的最新尝试:

Public Declare Function PCRSNewTrip Lib "C:\xxx\pcrsrv32.dll" Alias "_PCRSNewTrip" (ByRef myTripPtr As Long) As Long

Private Sub NewTrip_Click()

Dim myTrip As Long
Dim myTripPtr As Long

myTripPtr = VarPtr(myTrip)

myTrip = PCRSNewTrip(myTripPtr)

EndSub

我收到“错误的 DLL 调用约定”错误。

【问题讨论】:

Win32 VBA 仅支持STDCALL_CONVENTION 是什么? 另外ByRef 已经让你传递一个指针,所以你传递一个指向指针的指针。但这不应该导致这个错误。 来自 API 头文件:#if defined (BORLANDC) #define _IMPORT __declspec( dllimport ) #define _CONVENTION __stdcall #elif defined (_MSC_VER) #define _IMPORT _declspec( dllimport ) #define _CONVENTION _cdecl #endif 我不认为 C++ 的 long 与 VBA 的 Long 含义相同。我认为您追求的是 VBA 的LongPtr。 Reference 另外,_CONVENTION 显然因编译器而异。我不是 C++ 专家,但如果您使用 Microsoft 编译器进行编译,您会得到 _cdecl,这是不受支持的。它必须是 __stdcall 贯穿始终。 【参考方案1】:

猜测这是条件编译头代码的“实时”分支:

#elif defined (_MSC_VER)
#define  _IMPORT _declspec( dllimport )
#define  _CONVENTION _cdecl
#endif

_cdecl 在 Windows 上的 VBA 中不受支持。您需要使用使用__stdcall 的该DLL 的构建。

【讨论】:

我应该注意到我已经能够通过 MS Access VBA 成功地从这个 DLL 调用其他函数。这些函数只是初始化/关闭,如果有什么不同则不传递任何参数。 @creamer298 无参数函数可能与此有关,因为默认的 __cdecl 约定 requires each function call to include stack cleanup code(即 调用者),而在 __stdcall 中 callee 清理堆栈。没有参数,堆栈上什么都没有,要么工作。 @creamer298 CDecl 显然是在 VBA for Mac 中实现的。这就是Rubberduck flags its use in VBA code 的原因,因为这个 VBIDE 插件只能在 Windows 上运行,因此不会“看到”有条件地为 Mac 编译的代码。请注意,VBA 方面的 Declare 语句需要 CDecl 修饰符。 该 dll 的文档指出:“可以轻松集成到流行软件中,例如 Microsoft Access、Microsoft Excel 和使用 Visual Basic 和 Borland C++ 等软件开发环境构建的自定义应用程序。”并且它“是一个可以在 32 位 Windows 环境中运行的 32 位 DLL 产品。” 当然,给定标准调用。

以上是关于使用指针调用 C++ DLL 函数的主要内容,如果未能解决你的问题,请参考以下文章

将 C++ 结构指针从 Perl 传递给任意 dll 函数调用

C#调用C++的dll中的函数,数组指针的问题

C#怎么调用C++的dll?

C#调用C++ dll 回调

使用 C++ dll 进行特殊回调处理

ue4 c++ 怎么引入dll