0

I am using a DLL provided by a fellow programmer that offers certain functions I want to use in my application. The below code works as long as I use the imported functions in the same .cpp file - but not throughout all separate classes:

main.h

typedef void(*SendChat)(char*);

main.cpp

SendChat _SendChat;

HINSTANCE hMain = 0;
BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID)
{
    if(reason == DLL_PROCESS_ATTACH)
    {
        _beginthread(WorkerThread,0,NULL);

        hMain = LoadLibraryA("calculate.dll");
        if (hMain)
            _SendChat = (SendChat)GetProcAddress(hMain, "SendChat");
    }
    if (reason == DLL_PROCESS_DETACH)
    {
        //..
    }
    return 1;
}

The _SendChat works and does what it should do when I use it within main.cpp but as soon as I use it in the following class it does not work:

client.h

#include "main.h"

client.cpp

#include "client.h"

void MyClient::Send(char* Message)
{
    _SendChat(Message);
}

It makes sense as there's no definition of _SendChat anywhere in the client.cpp except I tried looking on how to solve this but I found nearly nothing - which makes me think I am not looking right.

Any hints are welcome.

Roel
  • 754
  • 3
  • 13
  • 30
  • Looking at your code i'm assuming you are building a dll. Did you debug at MyClient::Send and checked the _SendChat points to the one in GetProcAddress() return value? – XPD Aug 09 '15 at 07:28
  • Are you getting a compile or runtime error? What is the error? – Serge Rogatch Aug 09 '15 at 08:14
  • A compiler error: "_SendChat: identifier not found" in client.cpp. – Roel Aug 09 '15 at 08:15
  • What you are doing is illegal, DllMain() is not allowed to use LoadLibrary(). The usual result is deadlock on the loader lock. You've got a thread, it can call it. And friends don't let friends use GetProcAddress(), they give them an import library. – Hans Passant Aug 09 '15 at 09:04

2 Answers2

1

To fix the compile error you need to declare variable _SendChat to be visible in the file where you want to use it. In main.h after typedef void(*SendChat)(char*); you can write the following:

extern SendChat _SendChat;
Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158
  • Really, the moment I read this I wondered why I did not think of it myself. Thanks a lot. Sometimes I shouldn't listen to all the C programmers around me, with their way too complicated view on things. Thanks again. – Roel Aug 09 '15 at 08:33
1

The minimal path to a working solution would be to declare _SendChat as extren in your main.h file. This tells the compiler that this variable name is valid and declared somewhere, and the linker will sort it out at link time:

extern SendChat _SendChat;

However, doing this your cluttering up your global namespace and not being a good citizen. I'd argue that you should really put your DLL functions into their own namespace or class and let everything share it.

DLLFuncs.h

typedef void(*SendChatFunc)(char*);

namespace DLLFunctions
{
  SendChatFunc SendChat;
}

main.cpp

#include "DllFuncs.h"

HINSTANCE hMain = 0;
BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID)
{
    if(reason == DLL_PROCESS_ATTACH)
    {
        _beginthread(WorkerThread,0,NULL);

        hMain = LoadLibraryA("calculate.dll");
        if (hMain)
            DLLFunctions::SendChat = (SendChatFunc)GetProcAddress(hMain, "SendChat");
    }
    if (reason == DLL_PROCESS_DETACH)
    {
        //..
    }
    return 1;
}

client.cpp

#include "client.h"
#include "DLLFuncs.h"

void MyClient::Send(char* Message)
{
    DLLFunctions::SendChat(Message);
}
Donnie
  • 45,732
  • 10
  • 64
  • 86