我正在为第三方应用程序编写模块;应用程序uses __cdecl
调用约定。
与此同时,我有一个uses __stdcall
调用约定的遗留DLL。
我可以创建一端exports __cdecl
功能的包装器,而另一端imports __stdcall
功能吗?我还有哪些其他选择?
谢谢,
编辑:
以下是我的帮助澄清我的情况的一些额外信息。
third_party.exe
需要skeleton.dll
才能访问#ifdef _EXPORTING
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
DECLSPEC int ICD_Create(char* id);
...
...
...
。源代码skeleton.dll包含下面的头文件,并使用__cdecl进行编译。
Application: ThirdParty.exe (out of your control: Uses __cdecl)
|
|
Plugin module: Skeleton.dll (your code)
|
|
Legacy DLL: ModifiedVB6.dll (out of your control: Seem to work with __stdcall)
理想情况下,我会使用骨架源代码来开发我的DLL;遗憾的是,将当前的VB6遗留代码移植到C ++中太费时间了。鉴于此,我不得不通过跟随this guideline破解我的VB6代码(这是一个解决方法,但它允许我使用ActiveX DLL作为标准C DLL)。
我对修改后的VB6调用约定没有100%的信心,也不知道如何修改它。练习使用__stdcall,似乎与我开发的测试应用程序一起正常工作。但是,当我使用第三方应用程序测试它时,它会正确调用某些函数,但在其他函数中它会崩溃。
架构如下:
{{1}}
旧版DLL生成dll,lib和def文件;没有头文件。
答案 0 :(得分:4)
DLL通常会附带一个头文件(.h)和一个处理调用约定,导出函数原型等的相关导入库(.lib)。
只需包含头文件,链接到导入库,您就可以直接调用这些函数。
该头文件将指定函数使用__stdcall
调用约定。你肯定不会,也不应该写一个单独的包装DLL。这将增加一个完全无偿的复杂层。
重新阅读您的问题和评论后,我相信您拥有以下架构:
Application (out of your control)
|
|
Plugin module (your code)
|
|
Legacy DLL (out of your control)
旧版DLL使用__stdcall
导出其功能。应用程序使用__cdecl
从插件导入函数。
如果该概要正确,那么您当然必须使用__stdcall
从旧版DLL导入并使用__cdecl
导出到应用程序。由于界面的这些部分不在您的控制范围之内,因此您无法选择。
然而,我发现问题和评论很难遵循。也许我还没有完全理解。请随意添加更多信息,以便在编辑问题时进行澄清。
更新后,我怀疑你的问题都与如何将VB6遗留DLL与C ++ DLL接口有关。由于您没有VB6 DLL的头文件(.h),因此您可能正在编写自己的翻译。
如果我没记错的话,VB6只支持你当前正在使用的__stdcall
。因此,您的问题最有可能是由于导出的VB函数错误地转换为C ++原型。
我认为您最好的行动方案是专注于使这些原型翻译正确无误。也许您可以考虑在单独的独立测试项目的上下文中执行此操作,以避免整个应用程序的复杂性。
如果您需要Stack Overflow的进一步帮助,我认为您需要提供VB6函数声明和您尝试过的翻译,但我认为这将成为新问题的主题。
答案 1 :(得分:2)
__declspec(dllexport)
只需要告诉编译器从DLL导出标识符。这与您定义(可能)导出的函数的调用约定或您导入的函数的调用约定无关。这应该单独指定,__stdcall
很好(但请注意,vararg函数必须是__cdecl
,因为调用者必须清理堆栈。)
是的,您可以使用另一个导入它的DLL包装您的DLL并导出具有__cdecl
调用约定的函数,但它可能会混淆DLL的用户。我不会这样做,但它是可能的。