I need to load a DLL at runtime. I don't know in advance which DLL to load, but DLLs are the implementation of an interface (pure virtual method). The final goal is to have a pointer to a DLL to call its methods.
Now, I want to test just the DLL loading, calling a test method, but I fail. The test method is void test().
#if defined (_WIN32)
const path PluginExtension(".dll");
#define STDCALL __stdcall
#else
const path PluginExtension(".so");
#define STDCALL
#endif
extern "C"
{
typedef void* (STDCALL* CreatorFunction)();
constexpr auto FunctionName{ "CommandGeneratorEngine::Interface::test" };
}
auto library = LoadLibraryExW(pluginPath.native().c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
if (library != nullptr) {
auto creator = (CreatorFunction)GetProcAddress(library, FunctionName);
if (creator != nullptr) {
// do something
}
else
{
throw std::exception("Error when loading comm plugin");
}
The interface
namespace TGComm {
namespace CommandGeneratorEngine {
class Interface {
public:
using Ptr = std::shared_ptr<Interface>;
virtual ~Interface() = default;
virtual void test() = 0;
};
}
}
And the interface implementation:
class LHFImplementationInterface : public CommandGeneratorEngine::Interface
{
public:
void __declspec(dllexport) __stdcall test() override{
// do something...
}
};
The line
auto creator = (CreatorFunction)GetProcAddress(library, FunctionName);
returns a null value.
Solved.
I created a new header file, h1.h
#include "Global.h"
extern "C" {
LHCOMMQT_LIB void* createTGCommPlugin();
}
its cpp is
#include "h1.h"
#include "LHFImplementationinterface.h"
void* createTGCommPlugin() {
auto p = new LHFImplementationInterface();
return p;
}
and global.h is
#ifndef LHCOMM_GLOBAL_H
#define LHCOMM_GLOBAL_H
#include <QtCore/qglobal.h>
#ifdef LHCOMMQT_EXPORTS
# define LHCOMMQT_LIB Q_DECL_EXPORT
#else // ifdef LHCOMMQT_EXPORTS
# define LHCOMMQT_LIB Q_DECL_IMPORT
#endif // ifdef LHCOMMQT_EXPORTS
#endif // LHCOMM_GLOBAL_H
in main:
typedef void* (STDCALL* CreatorFunction)();
constexpr auto FunctionName{ "createTGCommPlugin" };
try {
auto library = LoadLibraryExW(pluginPath.native().c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
if (library != nullptr) {
auto creator = (CreatorFunction)GetProcAddress(library, FunctionName);
...
and now works good
Related
I'm working on a cross platform project where I have to load dynamic libraries. I therefore created a very basic platform independent templated wrapper class around dlopen/loadLibrary that act like a factory class and return unique_ptr<T>s of the lib object.
But this is very unpractical in most of the cases, I therefore wondered, how can I design a simple wrapper that can do the following:
Load a lib and become a factory on instances of that lib objects for when we have to use multiple instances of the lib object
Create a self managed entity (a struct containing a unique ptr on the object and the handle on the lib maybe ?) for when we want to use only one instance of a lib object and not bother with a factory
Use the library provided deleter (symbol "destroy") instead of the default one
Does this exist ? If not, what would be the best way to do this ?
My implementation so far:
#pragma once
#include <memory>
#include <iostream>
#if _WIN32
#include <Windows.h>
#else
#include <dlfcn.h> //dlopen
#endif
namespace utils
{
template <class T>
class DynLib
{
public:
DynLib() = default;
~DynLib()
{
if (handle_)
closeLib(handle_);
};
private:
bool printLibError()
{
#if _WIN32
std::cerr << GetLastError() << std::endl;
#else
std::cerr << dlerror() << std::endl;
#endif
return false;
}
void *openLib(const std::string &libName)
{
#if _WIN32
return LoadLibrary((libName + ".dll").c_str());
#else
return dlopen((libName + ".so").c_str(), RTLD_LAZY);
#endif
}
int closeLib(void *libHandle)
{
#if _WIN32
return FreeLibrary((HMODULE)libHandle);
#else
return dlclose(libHandle);
#endif
}
void *loadSymbol(void *libHandle, const char *sym)
{
#if _WIN32
return (void *)GetProcAddress((HMODULE)libHandle, sym);
#else
return dlsym(libHandle, sym);
#endif
}
public:
bool open(const std::string &filename, const char *csym = "create", const char *dsym = "destroy")
{
if (!(handle_ = openLib(filename)))
return printLibError();
if (!(create = (T * (*)()) loadSymbol(handle_, csym)))
return printLibError();
if (!(destroy_ = (void (*)(T *))loadSymbol(handle_, dsym)))
return printLibError();
return true;
}
std::unique_ptr<T> createUnique()
{
return (std::unique_ptr<T>(create()));
}
private:
void *handle_{nullptr};
T *(*create)();
void (*destroy_)(T *);
};
}
Have you considered Boost.DLL library?
It provides examples on how implement plugins/factory methods.
I have a dll plugin ,myDLL.cpp, which has the following code:
#include "myDLL.h"
#include "MainApp.h"
class A{
public:
// NOTE: SomeType is defined in main application code.
A(SomeType* data) : m_data{data}
void MemberFunc(){
// NOTE: do_something should access data in main application.
m_data->do_something();
}
private:
SomeType* m_data;
};
// exported function
A* createInstance(SomeType* data){
return new A(data);
}
In the main application I have:
stc::vector<int> IntArray;
class SomeType{
SomeType(){
IntArray.resize(1000);
}
void do_something(){
// manipulate IntArray's contents.
IntArray[rand() % IntArray.size()] = rand();
}
};
typedef A*(_createInstance)(SomeType*);
void main(){
// Load the Dll and get createInstance()
_createInstance createInstance = LoadMyDLL();
SomeType someType;
A* a = createInstance(&someType);
a->MemberFunc();
// Free the instance of A and unload the DLL.
UnloadMyDLL(a);
}
The dll code now can use the API of the main application, but it can't access the right data. When I put a break point at m_data->do_something(); and enter the method call, then I see that IntArray is empty. What am I doing wrong and how do I solve the problem?
I could succesfully run your example without experiencing your problem:
I assumed that in your headers there are only the class definitions and not definition of its member functions
So I buid a DLL project. But it failed producing the dll because of the missing do_something() function. Normal, because with your architecture it should be defined in the application not in the DLL ! I could solve the problem by making do_something() virtual.
Then I build the application. I first chose for simplicity and linked the application with the DLL (no loading issues). Unfortunately it didn't find either MemberFunc() nor createInstance(). I could solve this by exporting the DLL entry.
FInally I updated the application, to have a dynamic load of the library. For avoiding unnecessary hassle of having to find back MemberFunc(), I made it virtual as well.
In all the tests above, I had absolutely no problem. IntArray was always correct. In debug mode I could see it with the expected content, as soon as it entered the scope.
My conclusion, from these tests and looking at your snippet (expecially with doSomething not being virtual): your problem is probably that have defined SomeType class with functions and eventually IntArray in Main.h.
If this is the case, your DLL refers to its own copy of these elements and not as you think to those in main ! THis explains why you don't see the expected values !
Solution:
File MainApp.h:
class SomeType{
public:
SomeType();
virtual void do_something();
};
File MyDLL.h:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class A {
public:
A(SomeType* data);
virtual void MemberFunc(); // access through vtable. No need to link
private:
SomeType* m_data;
};
extern "C" { // use unmangled name for easo of use of dynamic loaded DLL
MYDLL_API A* createInstance(SomeType* data);
};
File MyDLL.cpp:
#define MYDLL_EXPORTS
#include "MainApp.h"
#include "MyDLL.h"
A::A(SomeType* data) : m_data{ data } {}
void A::MemberFunc(){ m_data->do_something(); }
extern "C" {
MYDLL_API A* cdecl createInstance(SomeType* data){ return new A(data); }
}
File main.cpp:
#include <Windows.h>
#include <iostream>
#include <vector>
#include "MainApp.h"
#include "MyDLL.h"
using namespace std;
vector<int> IntArray;
SomeType::SomeType(){
IntArray.resize(1000);
IntArray[0] = 1; IntArray[1] = 101; IntArray[2] = 10101;
}
void SomeType::do_something(){
for (int i = 0; i < 4; i++) // read
cout << IntArray[i] << endl;
IntArray[3] = 2702; // write
}
int main(int ac, char**av)
{
HINSTANCE LoadMe = LoadLibrary(L"MyDLL.dll");
if(LoadMe != 0)
cout << "DLL Library successfully loaded!\n";
else throw exception("DLL library failed to load!\n");
typedef A*(*_createInstance)(SomeType*);
_createInstance fcreateInstance = (_createInstance) GetProcAddress(LoadMe, "createInstance");
if (fcreateInstance)
cout << "DLL function found !\n";
else throw exception("Function not found in DLL!\n");
SomeType someType;
A* a = fcreateInstance(&someType);
a->MemberFunc();
cin.get();
}
I have a Problem and i am completely stuck.
First i show you the code:
Config for Building(NarviConfig.h):
#pragma once;
namespace Narvi
{
#ifdef NARVI_EXPORTS
#define _NarviExport __declspec(dllexport)
#else
#define _NarviExport __declspec(dllimport)
#endif
}
//-------------------------------------------
I have 2 Classes in a DLL like this:
The first One(NarviRoot.h):
Header:
#pragma once
#include "NarviConfig.h"
#include "NarviWindow.h"
namespace Narvi
{
class _NarviExport NarviRoot
{
public:
NarviRoot();
~NarviRoot();
public:
bool Init(void);
private:
NarviWindow* mWindow;
};
}
Source:-----------------------------
#include "NarviRoot.h"
namespace Narvi
{
NarviRoot::NarviRoot()
{
}
NarviRoot::~NarviRoot()
{
delete mWindow;
}
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
}
//-----------------------------------------------------------------
The window(NarviWindow.h):
Header
#pragma once
#include "NarviConfig.h"
namespace Narvi
{
class _NarviExport NarviWindow
{
public:
NarviWindow();
~NarviWindow();
};
}
Source:--------------------------------
#include "NarviWindow.h"
namespace Narvi
{
NarviWindow::NarviWindow()
{
}
NarviWindow::~NarviWindow()
{
}
}
And this is my Testapp
mRoot = new Narvi::NarviRoot();
mRoot->Init();
It seems to work, but the program crashes when calling
mWindow = new NarviWindow();
Inside of
bool NarviRoot::Init(void)
{
mWindow = new NarviWindow();
return true;
}
and i can't figure out why.
If i write:
NarviWindow* mWindow = new NarviWindow();
it doesn't crash.
The constructor of NarviWindow is doing nothing, but it seems he can't access the private member mWindow.
I am pretty sure it is a simple error i made, but i can't see the wood for the trees.
Thank you! :)
I have a c++ shared library that can generate some event. I've an interface for the listener and a class that is able to register observers and fire events.
This library may be used used from java, C# and C++ code( compiled with differenc compilers) so I've two file headers: *.h for ANSI C interface and *.hpp for use library directly from C++ code. Now I cannot figure how export observer pattern with a C-like interface.
Here is a little snippet of how code is structured.
// hpp file
class IListener
{
public:
virtual ~IListener() {}
virtual void event1( int ) = 0;
virtual void event2() = 0;
};
using IListenerPtr = std::shared_ptr< IListener >;
class Controller
{
public:
Controller( IListenerPtr listener );
void addListener( IListenerPtr listener );
private:
void threadFunc()
{
while ( true )
{
// an event occured
for ( auto& e : mListeners )
e->event1( 2 );
for ( auto& e : mListeners )
e->event2();
}
}
private:
std::vector< IListenerPtr > mListeners;
};
// h file
#if defined( __MSCVER ) || defined( __MINGW32__ ) || defined( __MINGW64__ )
# define LIB_CALLBACK __stdcall
# define LIB_CALL __cdecl
# if defined( AAMS_EXPORTS )
# define LIB_API __declspec( dllexport )
# else
# define LIB_API __declspec( dllimport )
# endif
#else
# define LIB_API
#endif // WIN32
typedef int libError;
LIB_API libError LIB_CALL libInit( ???? );
How can I make this library usable from C code? A first attempt maybe:
typedef struct libListenerTag
{
typedef void (LIB_CALLBACK *Event1Func)( int );
typedef void (LIB_CALLBACK *Event2Func)();
Event1Func Event1;
Event2Func Event2;
} libListener;
LIB_API libError LIB_CALL libInit( libListener* listener );
and in someway bind libListener to IListener
// cpp file
class CListener : public IListener
{
public:
CListener( libListener* listener
: mListener( listener )
{
}
void event1( int i ) { mListener->Event1( i ); }
void event2() { mListener->Event12(); }
private:
libListener* mListener;
}
Controller* g_controller = nullptr;
LIB_API libError LIB_CALL libInit( libListener* listener )
{
g_controller = new Controller( make_shared< CListener >( listener );
// ...
}
This method doesn't look very good for me. Is a better way to accomplish this?
You're missing something that's standard in C event callbacks: a context pointer.
In C++ your IListener subclass gets an implicit this pointer in its callbacks, meaning it can store state and context info in the instance.
For free functions, you don't have this, so you need to add an explicit argument.
/* c_interface.h */
typedef void (*EventCallback1)(void *context, int arg);
typedef void (*EventCallback2)(void *context);
struct Listener; /* opaque type */
struct Listener *create_listener(EventCallback1, EventCallback2, void *context);
void destroy_listener(struct Listener*);
so from the C side, you pack whatever state you need into a structure, pass it into create_listener as your context, and get it passed back to your functions when they're called.
// c_implementation.cpp
extern "C" {
#include "c_interface.h"
struct Listener: public IListener {
EventCallback1 cb1;
EventCallback2 cb2;
void *context;
Listener(EventCallback1 e1, EventCallback2 e2, void *c)
: cb1(e1), cb2(e2), context(c)
{}
virtual void event1(int arg) {
(*cb1)(context, arg);
}
virtual void event2() {
(*cb2)(context);
}
};
Listener *create_listener(EventCallback1 cb1, EventCallback2 cb2, void *context) {
return new Listener(cb1, cb2, context);
}
}
The client code looks something like
#include "c_interface.h"
struct MyContext {
int things;
double needed;
int to_handle;
char callbacks[42];
};
void cb0(void *context) {}
void cb1(void *context, int arg) {
struct MyContext *c = (struct MyContext *)context;
c->things = arg;
}
void foo() {
struct MyContext *context = malloc(sizeof(*context));
struct Listener *l = create_listener(cb1, cb0, context);
...
Say I have a DLL right that contains this:
//DLL
class foo {
static __declspec int Add(int a, int b)
{
return a+b
}
}
How Do I call it call the GetProc Address? I.e:
HINSTANCE hFoo = LoadLibrary("Foo.dll");
int* proc = NULL;
proc = (int*) GetProcAddress(hFoo, ??????);
//Main Exec linked to dll
How in the world would you get the address of a class created in a dll using GetProcAddress?
edtheprogrammerguy is right.
Here is more informations on how to get class properly exposed:
You need to prefix with the attribute :
__declspec(dllexport)...
all the features you want to expose.
See this.
Example for a C function:
__declspec(dllexport) int __cdecl Add(int a, int b)
{
return (a + b);
}
This can be simplified using MACROS: everything is explained on this helpful page.
For C++ classes, you only need to prefix each class (not every single method)
I usually do it that way :
Note : The following also ensures portability...
Include File :
// my_macros.h
//
// Stuffs required under Windoz to export classes properly
// from the shared library...
// USAGE :
// - Add "-DBUILD_LIB" to the compiler options
//
#ifdef __WIN32__
#ifdef BUILD_LIB
#define LIB_CLASS __declspec(dllexport)
#else
#define LIB_CLASS __declspec(dllimport)
#endif
#else
#define LIB_CLASS // Linux & other Unices : leave it blank !
#endif
Usage :
#include "my_macros.h"
class LIB_CLASS MyClass {
}
Then, to build, simply :
Pass the option -DBUILD_LIB to the usual compiler command line
Pass the option -shared to the usual linker command line
You can't get the address of a class from a .dll. If you want to use a class instance from a .dll, use dllexport/dllimport, which lets you export the class and use it as if it were declared locally.
Reference from Microsoft:
http://msdn.microsoft.com/en-us/library/81h27t8c(v=vs.80).aspx
I was trying to create an example of Explicit Linking Here is the example I finally came up with, I apologize for not specifically mentioning this earlier.
Here we go:
//DLL
#include "main.h"
#include <windows.h>
#include <stdexcept>
using namespace std;
class FOO{
static __declspec double ADD(double a, double b)
{
return a+b;
}
}
//EXEC
#include <windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
typedef double (*MYPROC)(double, double);
int main()
{
double d1 = 10;
double d2 = 30;
double retval;
MYPROC procx = NULL;
DWORD err;
HINSTANCE hDll = LoadLibrary("DynamicLinkTester.dll");
if(hDll != NULL)
{
cout << "Success";
procx = (MYPROC) GetProcAddress(hDll, "_ZN7MathDLL5MathX3ADDEdd");
if(NULL != procx )
{
retval= (procx)(d1, d2);
cout << retval;
}
}
}
If anyone was wondering the same thing as me:
While you can't explicitly call a class/object from a dll you can call its method.