【问题标题】:Stack issues when calling a DLL compiled with Visual C++ in GCC在 GCC 中调用使用 Visual C++ 编译的 DLL 时的堆栈问题
【发布时间】:2010-10-30 04:32:05
【问题描述】:

我正在尝试从我的程序中调用使用(我相信)Visual C++ 编译的 DLL 中的一些函数,该程序是使用 GCC 编译的。

为了调用 DLL 中的函数,我对 DLL 执行 LoadLibrary(),然后执行 GetProcAddress() 以获取特定函数的地址,然后调用该函数。该函数返回一个指向我要调用的 DLL 中函数的指针列表。

好吧,当我尝试调用这些函数时,它们无法正常工作。我通过调试器运行我的程序,看起来 DLL 库函数正在查找 ebp+8 处传递的参数之一,即使 GCC 已将其放在 ebp-24 处。

这看起来绝对像一个堆栈问题。更重要的是,当调用 DLL 函数的 GCC 程序函数返回时,我的程序崩溃了——所以堆栈发生了一些奇怪的事情。有谁知道我需要做什么才能解决这个问题?我无法访问 DLL 代码。

另外:我尝试将 __cdecl 和 __stdcall 放在程序源文件中的 DLL 函数定义之前,但这没有任何改变。

【问题讨论】:

    标签: visual-c++ dll gcc stack


    【解决方案1】:

    看起来像一个调用约定问题。确保将调用约定标签放在正确的位置。使用 GCC,它应该如下所示:

    typedef int (__stdcall *MyFunctionType)(int arg1, const char *arg2);
    MyFunctionType myFunction = (MyFunctionType)GetProcAddress(myModule, "MyFunction");
    // check for errors...
    int x = myFunction(3, "hello, world!");
    

    [编辑]

    看起来您的问题与调用约定无关(尽管正确处理它们很重要)。你误用了BSTRs——BSTR不是一个简单的char* 指针。它是一个指向 Unicode 字符串 (wchar_t*) 的指针,此外,在字符串的第一个字符之前隐藏了一个 4 字节长度的前缀。有关详细信息,请参阅MSDN。因此,对SetLicense() 的调用应如下所示:

    BSTR User = SysAllocString(L"");  // Not sure if you can use the same object here,
    BSTR Key = SysAllocString(L"");   // that depends on if SetLicense() modifies its
                                      // arguments; using separate objects to be safe
    // check for errors, although it's pretty unlikely
    (textCapLib.sdk)->lpVtbl->SetLicense((textCapLib.sdk), User, Key);
    SysFreeString(User);  // Hopefully the SDK doesn't hang on to pointers to these
    SysFreeString(Key);   // strings; if it does, you may have to wait until later to
                          // free them
    

    【讨论】:

    • 感谢您的回复。不幸的是,这正是它在 C 头文件中的样子。 VC++ 编译代码的方式和 GCC 编译代码的方式之间是否存在其他重大差异?堆栈对齐,还是...?只是一个注释;在库头文件中,它说这是编译库时的编译器设置:Oicf, W1, Zp8, env=Win32 (32b run) __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() 不确定这是否与它有关。
    • 能否贴出你正在使用的代码,包括头文件的相关部分和调用代码?
    • 当然。我在这里粘贴了库的头文件:pastebin.com/m2d66c18c。我在此处粘贴了一个示例(用 C 语言):pastebin.com/m564b3181。我正在使用带有 GCC 的 C 接口。相关代码从头文件的第 810 行开始。我可以很好地调用 Win32 API 函数,根据头文件,库函数与 WINAPI 函数具有相同的调用约定(STDMETHODCALLTYPE/WINAPI == __stdcall)
    • 我试过了,没区别。 SDK 附带一个示例源代码文件;我实际上是直接复制并粘贴了代码,所以我认为他们正确处理了数据类型。不幸的是,SDK 的作者仍然没有回复我(我猜是周末),所以我坚持认为图书馆的一切都是正确的,这对我来说是个问题。我只是下载 VC++ Express;我会看看我的代码在用它编译时是否有效。
    • 安装 VC++ 花了大约一个小时。然后我尝试编译并运行示例应用程序,我得到:“运行时检查失败 #0 - ESP 的值没有在函数调用中正确保存。这通常是调用一个调用声明的函数的结果具有使用不同调用约定声明的函数指针的约定。”我为该项目尝试了 __cdecl、__stdcall 和 __fastcall,但它仍然给了我错误消息。是什么赋予了?我肯定做错了什么,因为 SDK 包含一个可以正常工作的演示可执行文件。
    猜你喜欢
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多