GetProcAddress function returning NULL

4.3k views Asked by At

I tried to load C++ dll dynamically, first I loaded the dll using "LoadLibrary" function and it is getting its handle correctly. After that I tried to get the function pointer of DLL file function using "GetProcAddress", it is returning NULL. Please find my DLL code and testing application code and let me know where is going wrong in the code.

dummy2.h

namespace newer
{
  class dllclass
  {
    public:
        static __declspec(dllexport) int run(int a,int b);
  };
}

dummy2.cpp

#include <iostream>
using namespace std;

#include "dummy2.h"

namespace newer
{
  int dllclass::run(int a,int b)
  {
    return a+b;
  }
}

dummy1.cpp

#include "stdafx.h" 
#include <windows.h>

#include <iostream>
using namespace std;
typedef int (*Addition)(int,int);

int _tmain(int argc, _TCHAR* argv[])
{
  Addition add;
  HINSTANCE hDLL;
  hDLL = LoadLibrary(TEXT("Dummy2.dll"));

  add = (Addition)GetProcAddress(hDLL, "run");  

  getchar();
  return 0;
}

Please refer above code and guide me.

2

There are 2 answers

9
EmDroid On BEST ANSWER

It's because the name is mangled (i.e. the name of the function is not "run" but something different).

Your code will work with (for MSVC 2013 where I tested):

add = (Addition)GetProcAddress(hDLL, "?run@dllclass@newer@@SAHHH@Z");
cout << add(1, 2) << endl;

In general, if you want to load a class via plugin, your best shot is to use virtual interface. An example:

//dummy2.h
namespace newer
{
  class dllclass_interface
  {
    public:
        virtual int run(int a,int b) = 0;
 };

}

extern "C" __declspec(dllexport) newer::dllclass_interface* getDllClass();

//dummy2.cpp
#include <iostream>
using namespace std;

#include "dummy2.h"

namespace newer
{
  class dllclass: public dllclass_interface
  {
    public:
        virtual int run(int a,int b);
 };

  int dllclass::run(int a,int b)
  {
    return a+b;
  }
}

extern "C" newer::dllclass_interface* getDllClass()
{
    static newer::dllclass instance;
    return &instance;
}

typedef newer::dllclass_interface* (*GetClassFunc)();

GetClassFunc getClassFunc = (GetClassFunc)GetProcAddress(hDLL, "getDllClass");

newer::dllclass_interface* dllClass = getClassFunc();
cout << dllClass->run(a, b) << endl;
4
Kirill Kobelev On

In fact, DLLs were introduced back in the times of C. Since then C++ introduced function names overloading (depending on the types of parameters) and something called "mangled names" to allow linking function call with the proper name. C++ standard does not specify how this name should look like. Different compilers implemented embedding types of parameters into the names differently.

C++ understands this problem and sometimes it is necessary to have predictable name. There is special construct in C++ for that:

extern "C"
{
     int run(int, int);
}

When you specify the name of the function in GetProcAddress it should be exactly as it was exported from DLL. You can view these names using special utilities like DependencyWalker.