使用指针调用 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 函数的主要内容,如果未能解决你的问题,请参考以下文章