Ok, so, DLLs are getting mad annoying. Either because I'm a fool or they are really that complex.
I'm trying to have a DLL which contains a class and then export that class and use it via Run-Time Dynamic Linking, i.e. using LoadLibrary and GetProcAddress functions, without needed to link to a .lib.
I read that it's better to instead of exporting the class itself, you should export a function which returns an instance of said class. Something like this;
extern "C" {
Threader __declspec(dllexport)* CreateClass()
{
return new Threader();
}
};
How do I then do the whole "GetProcAddress" in the main to access this function. I can't seem to get it to work. I can export a regular function that just returns an int this way no issue, but with the class return I'm struggling. When I try to call the function, the compilier throws error;
LNK2019 unresolved external symbol "public: __cdecl Threader::Threader(void)" (??0Threader@@QEAA@XZ) referenced in function CreateClass
Here's my source code;
Main.cpp
#include <iostream>
#include "Threader.h"
#include "GetClass.h"
#include <Windows.h>
typedef int(__cdecl* MYPROC)(LPCWSTR);
typedef Threader* (* GETMYCLASS)(LPCWSTR);
int wmain()
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
GETMYCLASS ClassAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
hinstLib = LoadLibrary(TEXT("ThreaderDLL.dll"));
if (hinstLib != NULL)
{
std::cout << "DLL Loaded" << std::endl;
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "ThreadFunc");
GETMYCLASS ClassAdd = (GETMYCLASS) GetProcAddress(hinstLib, "CreateClass");
if (NULL != ProcAdd && NULL != ClassAdd)
{
std::cout << "Func Loaded, Class Loaded"<<std::endl; //**This line runs so ClassAdd is NOT empty**
fRunTimeLinkSuccess = TRUE;
ThreadFunc();
Threader* threader = CreateClass(); //This wont work causes build to fail
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
int i = 0;
double j = 0;
std::cout << "Hello World!\n";
Sleep(2000);
std::cout << "WakaWaka" << std::endl;
Sleep(2000);
return i;
}
Threader.h
#pragma once
#include <thread>
#include <iostream>
#include <vector>
#include <atomic>
#include <mutex>
class Threader
{
public:
Threader();
~Threader();
void makeThread();
int ThreadFunc();
std::vector<std::thread> threads;
std::atomic<bool> running = true;
static std::mutex mtx_;
std::atomic<int> i = 0;
private:
};
extern "C" {
Threader __declspec(dllexport)* CreateClass()
{
return new Threader();
}
};
extern "C" {
int __declspec(dllexport) __cdecl ThreadFunc()
{
int i = 0;
while (i < 500)
{
std::cout << i << "\n";
i++;
}
return 0;
}
};
Threader.cpp
#include "Threader.h"
#include <Windows.h>
std::mutex Threader::mtx_;
Threader::Threader()
{
}
Threader::~Threader()
{
//running = false;
std::cout << "Killing Class and joining threads" << std::endl;
for (auto& t : threads)
{
t.join();
}
}
void Threader::makeThread()
{
std::cout << "Making Class thread" << std::endl;
//std::thread thread(&Threader::ThreadFunc, this);
threads.push_back(std::thread(&Threader::ThreadFunc, this));
//thread.join();
//return 0;
}
int Threader::ThreadFunc()
{
std::cout << "Class Thread Started" << std::endl;
while (running)
{
while (i < 100)
{
std::lock_guard<std::mutex> lck(mtx_);
//std::cout << "i = " << i << "\n";
i++;
Sleep(1000);
}
running = false;
}
std::cout << "Class Thread Ending" << std::endl;
return 0;
}
Do I have to put the declaration of CreateCLass in the .h and the implementation in the .cpp? I know it has something to do with the compilier not finding the implementaiton or something like that. But I'm pretty sure I tried that and it still didn't work.
Plz help.