Tiago Aguiar

Como Gerar e Fazer Chamadas Entre DLL e Executáveis em C++

avatar
Preview Image

Skills Required: C++

Você precisará gerar uma DLL e um Executável:

  1. GameLib (dll)
  2. Game (executable)

Compilando

Vou dar um exemplo para compilar um executável. Insira suas flags de compilador, do linker e qualquer outro parâmetro que seu programa necessite.

1
cl  %COMPILE_FLAGS% -Fe:main -DINTERNAL_MODE ..\src\main.cpp -Fmain.map /link %LINKER_FLAGS% %STATIC_LIB%

Agora vamos gerar uma DLL.

Note que precisaremos usar o /LD para informar que é uma DLL, bem como /EXPORT: para indicar qual será o nome da função de dentro da DLL que queremos expor ao executável.

1
cl  %COMPILE_FLAGS% -Fe:game -DINTERNAL_MODE ..\src\game.cpp -Fmgame.map /LD /link %LINKER_FLAGS% /EXPORT:function1

Definições para DLL

No código onde terá a DLL, game.cpp e game.h, vamos definir alguns pointers para funções, veja um exemplo:

1
2
3
4
 // game.h
#define FUNCTION1(name) void name(Memory *memory)
typedef FUNCTION1(Function1);
FUNCTION1(function1);

No trecho acima, definimos uma macro para gerar a declaração da função e depois com typedef, criamos o pointer para essa função. E por útlimo, construímos nossa declaração para uma função de nome function1.

O tipo Memory será usado mais para frente. Ele é apenas um exemplo de parâmetros para a função.

Na implementação, vamos definir o conteúdo para a nossa função (que será chamada pelo executável).

1
2
3
4
5
 // game.cpp
extern "C" FUNCTION1(function1)
{
    // content..
}

No trecho acima, extern "C" é necessário para evitar o name mangling (alteração do nome da função) por parte do C++. Ou seja, mantenha no c-style.

Chamando Função da DLL a Partir do Executável

Agora, para chamar essas funções a partir do executável, carregue a DLL e depois o pointer para essa função.

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.cpp
// load lib
HMODULE dll = LoadLibraryA("gamelib.dll");

// load function
Function1 *function1 = (Function1 *) GetProcAddress(dll, "function1");

// using
Memory memory = {};
function1(&memory);

// free ending
FreeLibrary(dll);

Faça as checagem necessárias para NullPointer e comece a usar essa função.

Definições para Executável

Até o momento chamamos um função da DLL a partir do Executável. Agora, como chamar uma função do executável a partir da DLL?

Simples!

Adicione o header file game.h na main.cpp para poder implementar as funções.

1
2
3
4
 // game.h (lib)
#define FUNCTION2(name) void name(const char *filename)
typedef FUNCTION2(Function2);
FUNCTION2(function2);

E implemente essa função.

1
2
3
4
5
6
// main.cpp (exe)
FUNCTION2(function2)
{
   // content
   printf("hello %s", filename);
}

Chamando Função do Executável a Partir da DLL

Agora, quando for chamar a function1, você pode passar a function2 como pointer, dessa forma, a DLL conseguirá “ver” a função implementada no executável.

Você pode passar junto com o tipo Memory mencionado anteriormente:

1
2
3
4
5
// game.h (lib)
typedef struct
{
    Function2 *function2;
} Memory;
1
2
3
4
5
// main.cpp (exe)
// using
Memory memory = {};
memory.function2 = function2;
function1(&memory);
1
2
3
4
5
// game.cpp (lib)
extern "C" FUNCTION1(function1)
{
    memory->function2("world");
}

Claramente este é um exemplo pequeno, mas totalmente prático que você pode adicionar mais e mais funções para comunicar a sua DLL com seu executável.

Lembre-se sempre de carregar no início do programa, checar os nullpointers e por fim, livrar a DLL com o FreeLibrary.

Espero ter ajudado!

Maravilha! Em breve você receberá conteúdos exclusivos por e-mail. Continue lendo os artigos para aprender mais sobre programação.