Reputation: 81
I have a DLL file which has a class called trial and it contains a function called test, I have another project in which I loaded the DLL using the loadlibrary function from the windows module, now I want to know how to create an object of type trial in the new project.
I tried defining the class as "class __declspec(dllexport) trial" but I don't know how to create an object in the main file now.
Trail.h is as follows:
class __declspec(dllexport) TRIALSHARED_EXPORT Trial
{
public:
Trial();
void test();
};
Trail.cpp is as follows:
extern "C"{
Trial::Trial(){
cout<<"object is created"<<endl;
}
void Trial:: test(){
cout<<"dynamic thingy"<<endl;
}
}
The main function is as follows:
int main()
{
HINSTANCE here=LoadLibrary(L"C:\\Users\\vinay\\Documents\\qt c++\\build-trial-Desktop_Qt_5_12_0_MinGW_64_bit-Debug\\debug\\trial.dll");
if(!here){
cout<<"could not load the lib"<<std::endl;
}
else{
cout<<"library loaded"<<endl;
typedef void(*FNPTR)();
FNPTR fn=FNPTR(GetProcAddress(here,"Trial"));
fn();
}
}
Upvotes: 1
Views: 4191
Reputation: 13690
If you can't use load-time binding you should use a pattern with a factory. The factory creates an instance of an object that implements an interface. The interface is a abstract class that can be used in the consumer.
Change your header file like this:
class ITrial
{
public:
virtual void test() = 0;
};
class Trial : ITrial
{
public:
Trial();
virtual void test() override;
};
// declare a function name that can be easily found with GetProcAdress.
extern "C" TRIALSHARED_API ITrial* CreateTrial();
typedef ITrial* (*PFN_Factory)();
Edit: The class ITrial
is the interface to the functionality. You define a contract between the implementation and the consumer of the DLL. Only members that are defined here can be accessed. The DLL defines a class that is inherited from the interface class as the implementing class. The implementing class can have any additional member as it needs.
Edit end.
The header file must not include the __declspec(dllexport)
. The macro TRIALSHARED_EXPORT
should be defined using conditional compilation.
#ifdef TRIAL_EXPORTS // defined only in the exporting DLL project
#define TRIALSHARED_API __declspec(dllexport)
#else
#define TRIALSHARED_API __declspec(dllimport)
#endif
Add to your Trial implementation:
ITrial* CreateTrial()
{
return new Trial;
}
Change your main function:
int main()
{
auto here=LoadLibrary(L"C:\\Users\\vinay\\Documents\\qt c++\\build-trial-Desktop_Qt_5_12_0_MinGW_64_bit-Debug\\debug\\trial.dll");
if(!here) {
cout<<"could not load the lib"<<std::endl;
return 1;
}
auto factory = reinterpret_cast<PFN_Factory>(GetProcAddress(here, "CreateTrial"));
if (!factory) {
cout<<"could not find factory"<<std::endl;
return 1;
}
auto pTrial = factory();
if (!pTrial) {
cout<<"factory failed"<<std::endl;
return 1;
}
pTrial->test();
delete pTrial;
}
The error handling is a bit clumsy. Change it as you need.
Upvotes: 4
Reputation: 51825
There are numerous errors in your code and, more importantly, in the approach you are taking. First, you need to define class Trial
as __declspec(dllexport)
when you build the DLL but as __declspec(dllimport)
when you build the EXE! This is conventionally done using pre-processor decisions, like so:
#ifdef _DLL // Assuming a Windows DLL build
#define IMPOREXP __declspec(dllexport)
#else
#define IMPOREXP __declspec(dllimport)
#endif
class IMPOREXP Trial
{
public:
Trial();
void test();
};
Next - and critically - you can't use a class defined in a DLL unless you use implicit 'load-time binding'! The LoadLibrary()
and GetProcAddress()
functions can do nothing about exported/imported classes.
I can give more, if you think it will be useful: comment a question or 'accept', and I'll try to guide you through the process with further examples.
Upvotes: 3