我正在导出 dll,但 GetProcAddress 返回 127 错误,如何解决?

发布于 2024-09-06 16:24:17 字数 1099 浏览 7 评论 0原文

#include "Calc.h"
#include<iostream>
#include <windows.h>
#include <WINERROR.H.>

typedef void (WINAPI * PCTOR) ();
int main()
{
    HMODULE hMod = LoadLibrary (L"Calci.dll");
    if (NULL == hMod)
    {
        printf ("LoadLibrary failed\n");
        return 1;
    }
    CCalc *pCCalc = (CCalc *) malloc (sizeof (CCalc));
    if (NULL == pCCalc)
    {
        printf ("memory allocation failed\n");
        return 1;
    }
    PCTOR pCtor = (PCTOR) GetProcAddress (hMod, "CCalc");//127 error
    int err = GetLastError();
    if (NULL == pCtor)
    {
        printf ("GetProcAddress failed\n");
        return 1;
    }
    __asm { MOV ECX, pCCalc };
    pCtor ();
    return 0;
}

//dll file
#include <tchar.h>


#ifdef CALC_EXPORTS
#define CALC_API __declspec (dllexport)
#else
#define CALC_API __declspec (dllimport)
#endif

#define SOME_INSTN_BUF        260

class CALC_API CCalc
{
private:
char m_szLastUsedFunc[SOME_INSTN_BUF];

public:
    CCalc (); 

    int Add (int i, int j);
    int Sub (int i, int j);
    TCHAR* GetLastUsedFunc ();

};
#include "Calc.h"
#include<iostream>
#include <windows.h>
#include <WINERROR.H.>

typedef void (WINAPI * PCTOR) ();
int main()
{
    HMODULE hMod = LoadLibrary (L"Calci.dll");
    if (NULL == hMod)
    {
        printf ("LoadLibrary failed\n");
        return 1;
    }
    CCalc *pCCalc = (CCalc *) malloc (sizeof (CCalc));
    if (NULL == pCCalc)
    {
        printf ("memory allocation failed\n");
        return 1;
    }
    PCTOR pCtor = (PCTOR) GetProcAddress (hMod, "CCalc");//127 error
    int err = GetLastError();
    if (NULL == pCtor)
    {
        printf ("GetProcAddress failed\n");
        return 1;
    }
    __asm { MOV ECX, pCCalc };
    pCtor ();
    return 0;
}

//dll file
#include <tchar.h>


#ifdef CALC_EXPORTS
#define CALC_API __declspec (dllexport)
#else
#define CALC_API __declspec (dllimport)
#endif

#define SOME_INSTN_BUF        260

class CALC_API CCalc
{
private:
char m_szLastUsedFunc[SOME_INSTN_BUF];

public:
    CCalc (); 

    int Add (int i, int j);
    int Sub (int i, int j);
    TCHAR* GetLastUsedFunc ();

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痴意少年 2024-09-13 16:24:17

使用 dumpbin.exe 检查 DLL 中导出的确切名称。也许它根本不存在?

如果你有机会使用导入库而不是 LoadLibrary API,那就更好了。

Use dumpbin.exe to check the exact name of the export in the DLL. Maybe it doesn't exist at all?

If you have a chance to use import library instead of LoadLibrary API, it is better.

凶凌 2024-09-13 16:24:17

您正在调用 GetProcAddress (hMod, "CCalc"),但是 "CCalc" 不是函数的名称:它是类的名称。

您正在尝试加载 CCalc::CCalc 默认构造函数的地址:为此,请使用工具(例如 dumpbin)来发现“修饰”名称构造函数。

然而,实现此功能的更常见方法是在 DLL 中创建静态工厂方法,而不是尝试动态加载和调用构造函数,例如:

class CALC_API CCalc 
{ 
public:
    static CCalc* create() { return new CCalc(); }

private:
    //doesn't need to be public because users instantiate this class using 
    //the static create method
    CCalc();  

public:
    virtual int Add (int i, int j); 
    virtual int Sub (int i, int j); 
    virtual TCHAR* GetLastUsedFunc ();

    virtual ~CCalc() {}
};

然后使用 GetProcAddress 获取静态 CCalc:: 的地址创建函数,因为它是静态的,所以您可以调用该函数,而无需使用程序集来干扰 ECX

You're invoking GetProcAddress (hMod, "CCalc"), however "CCalc" isn't the name of a function: it's the name of a class.

You're trying to load the address of the CCalc::CCalc default constructor: to do that, use a tool (e.g. dumpbin) to discover the "decorated" name of the constructor.

However instead of trying to dynamic-load and invoke the constructor, a more usual way to implement this functionality would be to create a static factory method in the DLL, e.g. like this:

class CALC_API CCalc 
{ 
public:
    static CCalc* create() { return new CCalc(); }

private:
    //doesn't need to be public because users instantiate this class using 
    //the static create method
    CCalc();  

public:
    virtual int Add (int i, int j); 
    virtual int Sub (int i, int j); 
    virtual TCHAR* GetLastUsedFunc ();

    virtual ~CCalc() {}
};

Then use GetProcAddress to get the address of the static CCalc::create function, which because it's static you can invoke without using assembly to mess with ECX.

凡间太子 2024-09-13 16:24:17

您不能对类使用 GetProcAddress。这是行不通的。只有您可以解析其名称的函数才是未损坏的“C”函数。

例如:

extern "C" __declspec(dllexport) CCalc *create_calc()
{
     return new CCalc;
}

现在,您可以使用以下方法解决它。

GetProcAddress(halnder,"create_calc");

由于 create_calc 是未损坏的函数。

此外,您还必须提供没有实现的抽象 API 类,并使 CCalc 继承 ACalc,否则您将得到无法解析的符号来编译您的应用程序。因为应用程序不知道实际的 addremove 成员函数。

class ACalc {
public:
      virtual add(int i,int j) = 0;
      ...
      virtaul ~ACalc() {}
};

class CCalc : public ACalc {
public:
      virtual add(int i,int j) { ... };
      ...
};

并且在主程序中

ACalc *ptr= call_for_dll_function

You can't use GetProcAddress for classes. This does not work. Only functions you can resolve their names are unmangled "C" functions.

For example:

extern "C" __declspec(dllexport) CCalc *create_calc()
{
     return new CCalc;
}

Now, you can resolve it using.

GetProcAddress(halnder,"create_calc");

As create_calc is not-mangled function.

Also you will have to provide abstract API class without implementation and make CCalc inherit ACalc, otherwise you'll get unresolved symbols tying to compile your application. Because actual add and remove member functions are not known to the application.

class ACalc {
public:
      virtual add(int i,int j) = 0;
      ...
      virtaul ~ACalc() {}
};

class CCalc : public ACalc {
public:
      virtual add(int i,int j) { ... };
      ...
};

And in the main program

ACalc *ptr= call_for_dll_function
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文