0

I am asking for help in implementing the proper freeing of memory in the dll library.

The structure of my project looks like this:

Library.dll:

  • interface.h -> base class definition with pure virtual methods
  • implementation.h -> derived class inheriting from public base
  • implementation.cpp -> derived class methods definition

implementation.h contains also exported functions:

extern "C" __declspec(dllexport) Base* __stdcall Create()
{
    return new Derived;
}

extern "C" __declspec(dllexport) void __stdcall Delete(Base* B)
{
    delete B;
}

Apllication.exe code looks like this:

#include "interface.h"
#include "windows.h"
#include <iostream>
#include <memory>

typedef Base* (*CREATE_BASE)();
std::unique_ptr<Base> SmartPointer;

int main()
{
    // Load the DLL
    HINSTANCE dll_handle = ::LoadLibrary(TEXT("Library.dll"));
    if (!dll_handle) {
        std::cout << "Unable to load DLL!\n";
        return 1;
    }

    // Get the function from the DLL
    CREATE_BASE Fn = (CREATE_BASE)GetProcAddress(dll_handle, "Create");
    if (!Fn) {
        std::cout << "Unable to load Create from DLL!\n";
        ::FreeLibrary(dll_handle);
        return 1;
    }

// i have possibility to use only C++11 so creation of unique_ptr looks like this:
SmartPointer = std::unique_ptr<Base>(Fn());

// ... do something like SmartPointer->Action();
::FreeLibrary(dll_handle);
return 0;
}

The code above works and I can easily initialize the Base object and perform functions from the Derived class. Now i would like to use the exported "Delete" function as a custom pointer deleter now. So I prepared the definition of the type:

typedef void (*DELETE_BASE)(Base* B);

and I would like to use it more or less like this:

DELETE_BASE DeleteFn=(DELETE_BASE)GetProcAddress(dll_handle,"Delete");
SmartPointer = std::unique_ptr<Base>(Fn(),DeleteFn);

However, I get a compiler error that this unique_ptr definition is incorrect. How to fix this?

My current solution is based on:

YatShan
  • 425
  • 2
  • 8
  • 22
Umberto
  • 25
  • 3

1 Answers1

1

The type of the deleter function must be specified since you want to override the default deleter (refer to std::unique_ptr<>).

Where you have used:

std::unique_ptr<Base>

you would instead want to use:

std::unique_ptr<Base, DELETE_BASE>
Phil Brubaker
  • 1,257
  • 3
  • 11
  • 14
  • As you suggest i made changes: std::unique_ptr SmartPointer; and SmartPointer=std::unique_ptr(Fn(),DeleteFn); but i get compiler error: Static assert failed: 'unique_ptr constructed with null deleter pointer' – Umberto Feb 20 '20 at 10:38
  • The `std::unique_ptr` cannot be default-constructed, so move the declaration to the assignment, e.g., `std::unique_ptr SmartPointer = std::unique_ptr(Fn(), DeleteFn);`. – Phil Brubaker Feb 20 '20 at 10:47
  • Thank you for quick response. It looks like it works but here a new question arises - as you probably guessed, my final implementation to support functions from a dll file is a bit more complex. The mentioned unique_ptr was supposed to be a member of another class, which contains functions that were to use it after initialization. In this case, when I declare and initiate at the same time it is not possible. Is there any way to store this pointer like a class member? – Umberto Feb 20 '20 at 11:06
  • While not very elegant and I haven't tried it, I think you could wrap it in another `std::unique_ptr<>`, e.g., `std::unique_ptr> myMember`, which would allow default construction of `myMember`, then to assign it you would use something like `instance.myMember = std::make_unique>(Fn(), DeleteFn));`. – Phil Brubaker Feb 20 '20 at 12:25