【问题标题】:Exporting a function, cast into a pointer through a DLL导出函数,通过 DLL 转换为指针
【发布时间】:2015-11-12 08:23:55
【问题描述】:

这是对先前问题的详细说明:How to reset state machines when unit testing C
还有一个类似的问题,但我的答案与我的问题不符,我想举一些例子:Exporting a function pointer from dll

我有两组代码,我希望它们应该做同样的事情,但后者会崩溃。 使用mingw32和Win7。

要导出的函数。这被认为是遗留的和不可变的。
addxy.c

    int addXY(int x, int y)
    {
      return x + y;
    }    

addxy.h

    int addXY(int x, int y);

工作示例

main.c

    #include <stdio.h>
    #include "addxy.h"

    typedef int (__cdecl *addXYWrap_t)(int a, int b);

    addXYWrap_t addXYWrap = (addXYWrap_t)addXY;

    void main()
    {
      printf("result: %d", addXYWrap(3, 4));
    }

产量

result: 7

崩溃的例子

addxydll.c

    #include <stdio.h>
    #include "addxy.h"

    typedef int (__cdecl *addXYWrap_t)(int a, int b);

    __declspec(dllexport) addXYWrap_t addXYWrap = (addXYWrap_t)addXY;

main.c

    #include <windows.h>
    #include <stdio.h>

    typedef int (__cdecl *func)(int a, int b);

    void main()
    {
      HINSTANCE loadedDLL = LoadLibrary("addxy.dll");

      if(!loadedDLL) {
        printf("DLL not loaded");
        return;
      } else {
        printf("DLL loaded\n");
      }

      func addition = (func)GetProcAddress(loadedDLL, "addXYWrap");

      if(!addition) {
        printf("Func not loaded");
        return;
      } else {
        printf("Func loaded\n");
      }

      printf("result: %d", addition(3, 4));
    }

产量

DLL loaded
Func loaded

在它崩溃之前。

崩溃没有提供有关原因或原因的任何信息。
是语法错误还是概念错误?

【问题讨论】:

  • __declspec(dllexport) 是指定您正在导出函数。在这种情况下,您既不导入也不导出,因为您正在进行运行时查找,因此请删除说明符。
  • GetProcAddress(loadedDLL, "addXYWrap"); 地址 addXYWrap - 它返回func*,而不是func
  • @immibis func 已经是函数指针类型了。
  • @Olipro 是的,在这种情况下 GetProcAddress 返回一个指向函数指针的指针。
  • @immibis 啊,是的,正确。他应该导出函数本身而不是函数指针。或者,他当然可以取消引用 GetProcAddress() 结果。

标签: c++ c function-pointers dllexport


【解决方案1】:
func addition = (func)GetProcAddress(loadedDLL, "addXYWrap");

GetProcAddress 的调用返回addXYWrap地址,而不是它的值。由于addXYWrap 是一个函数指针(与func 的类型相同),这意味着它返回一个指向函数指针的指针,或者一个func*

尝试将该行更改为:

func addition = *(func*)GetProcAddress(loadedDLL, "addXYWrap");

 

或者,或者:

func* addition = (func*)GetProcAddress(loadedDLL, "addXYWrap");

然后(*addition)(3, 4)

【讨论】:

  • 该死的你是陛下!我选择了第一个变体,谢谢。
【解决方案2】:

因此,根据上面的 cmets,您似乎想多了。如果您确实需要一个函数指针,那么要正确调用它,您必须首先取消引用GetProcAddress,如下所示:

func addition = *(func*)GetProcAddress(loadedDLL, "addXYWrap");

然而,一个更方便的解决方案是只包装函数:

__declspec(dllexport) int myAddXY(int x, int y)
{
    return addXY(x, y);
}

【讨论】:

    【解决方案3】:
    int addXY(int x, int y)
    {
      return x + y;
    }
    __declspec(dllexport) addXYWrap_t addXYWrap = (addXYWrap_t)addXY;
    

    这是一个错误。您必须导出函数,而不是全局指针。也就是说,

    /* addxy.c */
    __declspec(dllexport) int addXY(int x, int y)
    {
      return x + y;
    }
    ....
    /* main.c */
    func addition = (func)GetProcAddress(loadedDLL, "_addXY");
    

    【讨论】:

    • 问题是如何从 DLL 中导出函数指针,而不是函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多