lundi 31 octobre 2022

VS 2022 C++ DLL dllexport with Classes

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.

Aucun commentaire:

Enregistrer un commentaire