Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate a class in exported DLL function using getProcAddress

I have following .h code for DLL and using getProcAddress to consume DLL in another code.

// MathFuncsDll.h

#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif

namespace MathFuncs
{
    // This class is exported from the MathFuncsDll.dll
    class MyMathFuncs
    {
    public:
        int x = 10;
        MyMathFuncs();

           // Returns a + b + x
           MATHFUNCSDLL_API double Add(double a, double b); 

    };
}

And corresponding .cpp code is

// MathFuncsDll.cpp : Defines the exported functions for the DLL application. 
//

#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>

using namespace std;

namespace MathFuncs
{
    MyMathFuncs ::MyMathFuncs()
    {
            x = 10;
    }

    double MyMathFuncs::Add(double a, double b)
    {
        return a + b + x;
    }

}

The function Add is exported and it adds a and b along with initial value of x = 10.

I have created a DLL file of same and calling the functions using LoadLibrary and GetProcAddress.

The code works fine when I do not use constructor and directly add 10 i.e a + b + 10. But it fails when I do a + b + x, and basically constructor is not called.

How to instantiate such object using GetProcAddress so that when I load DLL and call function I get instantiated object method.

like image 785
Gaurav Avatar asked Dec 06 '25 04:12

Gaurav


1 Answers

Calling the constructor is not automatic. This is normally taken care of by the C++ compiler when you use operator new but that is no longer being done. You will have to use GetProcAddress() to get the constructor address and invoke it.

And before you do that, you have to allocate memory for the object. Whose address you pass to the constructor. This is where it gets difficult, you have no idea how much memory to allocate. It is guessable for a simple class like this one but optimizations applied by the C++ compiler when the class has virtual methods or implements multiple inheritance rapidly make this unpractical.

This is a big reason that interop with C++ is so difficult and poorly supported by other language runtimes. The only reliable way to do it is to also export a class factory function, a simple function that uses the new operator to create the object and return the pointer. There's now also a problem with destroying the object, you need some kind of memory manager that ensures that the correct implementation of operator delete is called as well. Typically done by reference counting, like std::shared_ptr<>.

All and all, you'll be well on your way to re-inventing COM.

like image 147
Hans Passant Avatar answered Dec 07 '25 19:12

Hans Passant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!