Я экспортирую DLL, но GetProcAddress возвращает ошибку 127, как ее решить? - PullRequest
0 голосов
/ 23 июня 2010
#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 ();

};

Ответы [ 3 ]

0 голосов
/ 23 июня 2010

Вы вызываете 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 :: create, которую, поскольку она статическая, можно вызывать без использования ассемблера, чтобы связываться с ECX.

0 голосов
/ 23 июня 2010

Вы не можете использовать GetProcAddress для классов.Это не работает.Только функции, которые вы можете разрешить по их именам, являются непонятными функциями "C.".

Например:

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

Теперь вы можете разрешить это, используя.create_calc - это не управляемая функция.

Также вам нужно будет предоставить абстрактный API-класс без реализации и заставить CCalc наследовать ACalc, в противном случае вы получите неразрешенные символы, связывающие компиляцию вашего приложения.Поскольку действительные функции-члены add и remove не известны приложению.

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
0 голосов
/ 23 июня 2010

Используйте dumpbin.exe, чтобы проверить точное имя экспорта в DLL. Может, его вообще не существует?

Если у вас есть возможность использовать библиотеку импорта вместо LoadLibrary API, лучше.

...