Tag: SO2 – 2021 – Ficha 3 v.2.6 – DLL.pdf

sessão 3 – DLL – Bibliotecas de ligação dinâmica

Bibliografia de apoio:
Material das aulas teóricas e incluindo documentos de apoio ao tópico de bibliotecas dinâmicas
Capítulo 5 do Livro Windows System Programming (da Bibliografia) (pags. 167 em diante)

MSDN:
Run-Time Dynamic Linking (Overview geral) https://docs.microsoft.com/en-us/windows/win32/dlls/run-time-dynamic-linking
Using Run-Time Dynamic Linking (Inclui exemplos) https://docs.microsoft.com/en-us/windows/win32/dlls/using-run-time-dynamic-linking
Referência do API para lidar com DLL (libloaderapi) https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/

Manipulação do registry: cria uma chave (se não existir), e abre a chave

#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

#define TAM 200

int _tmain(int argc, TCHAR* argv[]) {
    HKEY chave;
    TCHAR nome[TAM] = TEXT("SOFTWARE\\SO2");
    TCHAR par_nome[TAM] = TEXT("1º autor");
    TCHAR par_valor[TAM] = TEXT("João Sá");
    DWORD o_que_aconteceu;
    DWORD n_vezes = 1;
    DWORD tam = sizeof(DWORD);

#ifdef UNICODE 
    _setmode(_fileno(stdin), _O_WTEXT);
    _setmode(_fileno(stdout), _O_WTEXT);
    _setmode(_fileno(stderr), _O_WTEXT);
#endif

    if (RegCreateKeyEx(HKEY_CURRENT_USER, nome, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &chave, &o_que_aconteceu) == ERROR_SUCCESS)
    {
        if (o_que_aconteceu == REG_CREATED_NEW_KEY)
        {
            _tprintf(TEXT("chave %s criada com sucesso !"), nome);
            RegSetValueEx(chave, par_nome, 0, REG_SZ, (LPBYTE)par_valor, (_tcslen(par_valor) + 1) * sizeof(DWORD));
            RegSetValueEx(chave, TEXT("Número de execuções"), 0, REG_DWORD, (LPBYTE)&n_vezes, sizeof(DWORD));
        }
        else
        {
            _tprintf(TEXT("chave %s aberta com sucesso\n"), nome);
            RegQueryValueEx(chave, TEXT("Número de execuções"), 0, NULL, (LPBYTE)&n_vezes, &tam);
            n_vezes++;
            _tprintf(TEXT("Esta é a %d vez que o programa é executado"), n_vezes);
            RegSetValueEx(chave, TEXT("Número de execuções"), 0, REG_DWORD, (LPBYTE)&n_vezes, sizeof(DWORD));
        }
        return -1;
    }
    else
    {
        _tprintf(TEXT("Erro ao abrir/criar chave %s"), nome);
    }
    RegCloseKey(chave);
    return 0;
}

Referência do API para lidar com DLL: LINK
Fazer a leitura pelo modo implícito na arquitetura x86

//base.c
#include "principal.h"
#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

int _tmain(int argc, TCHAR* argv[])
{
    double local;
	
#ifdef UNICODE 
    _setmode(_fileno(stdin), _O_WTEXT);
    _setmode(_fileno(stdout), _O_WTEXT);
    _setmode(_fileno(stderr), _O_WTEXT);
#endif
    //usar a variavel DLL
	do
	{
		_tprintf(TEXT("Valor atual para a variavel global da DLL:%lf\nNovo valor:"), factor);
		_tscanf_s(TEXT("%lf"), &factor);
		_tprintf(TEXT("Valor atual para a variavel global da DLL:%lf\n"), factor);
		_tprintf(TEXT("Valor a passar como argumento à função da DLL:"));
		_tscanf_s(TEXT("%lf"), &local);
		_tprintf(TEXT("Resultado da função da DLL:%lf\n"), applyFactor(local));
	} while (factor != -1);

    return 0;
}

 

//base.h
#pragma once

#include <windows.h>

#ifdef SO2F3DLL_EXPORTS
#define DLL_IMP_API __declspec(dllexport)
#else
#define DLL_IMP_API __declspec(dllimport)
#endif

DLL_IMP_API double factor;
//variavel global, serve para cada processo
//cada processo acede à sua

DLL_IMP_API double applyFactor(double v); //funcao

carregar para o projeto o ficheiro .LIB, e colocar o ficheiro DLL na pasta do executável

Fazer a leitura pelo modo explicito
_mais independente
_mais controlo ao programador (pode ser usada apenas na altura em que preciso: da variável, da função, .. que está na DLL)
_só preciso quando for executar o programa
_não vai ser necessário o ficheiro h com a “estrutura” que consta no DLL

#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

#define TAM 256

int obterValorUtilizador()
{
	int valor = 0;
	TCHAR buffer[TAM] = _TEXT("");
	//obter o nome da chave
	_tprintf(_TEXT("introduza um valor: "));
	fflush(stdin);
	_fgetts(buffer, TAM, stdin);
	//retirar o \n
	buffer[_tcsclen(buffer) - 1] = '\0';
	valor = _tstoi(buffer);
	return valor;
}



int _tmain(int argc, TCHAR* argv[])
{
	int a, b;
	int sair = 0;

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif

	_tprintf(TEXT("Valor inicial da variavel da DLL \n \n"));
	double (*ptrVar)(double) = NULL;
	double (*ptrFunc)(double) = NULL;
	HINSTANCE hLib = LoadLibrary(TEXT("so2x86.dll"));

	if (hLib != NULL)
	{
		ptrFunc = (double(*)(double))GetProcAddress(hLib, "applyFactor");
		ptrVar = (double(*)(double))GetProcAddress(hLib, "factor");
		_tprintf(TEXT("parte2\n \n"));
		if (ptrVar != NULL &amp;amp;&amp;amp; ptrFunc != NULL)
		{
			_tprintf(TEXT("parte3\n \n"));
			_tprintf(_TEXT("Valor inicial da variavel da DLL: %f\n"), *((double*)ptrVar));
			do
			{
				a = 0;
				b = 0;
				_tprintf(_TEXT("vairavel (a)\n"));
				a = obterValorUtilizador();
				if (a == 1)
				{
					sair = 1;
					break;
				}
				*((double*)ptrVar) = (double)a;
				_tprintf(_TEXT("Valor novo da variavel da DLL: %f\n"), *((double*)ptrVar));

				b = obterValorUtilizador();
				_tprintf(_TEXT("Valor novo da variavel da DLL: %f\n"), ptrFunc(b));
			} while (sair != 1);
		}
		if (hLib != NULL)
		{
			FreeLibrary(hLib);
		}
	}
	return 0;
}

Criar uma DLL
Mudar o projeto para concretizar uma DLL e não um ficheiro executavel (nas propriedades do projeto)

O visual studio sugere uma variável de nome _WINDLL

//source.c
#include <tchar.h>
#include <stdlib.h>
//#define SO2F3DLL_EXPORTS
//vou usar a constante sugerida pelo VS


#include <time.h>

#include "Header.h" //deve ser feito depois do define

double varGlobal = 4;
int varInternaDLL = 5;

double aplicarFactor(double argumento)
{
	_tprintf(_TEXT("esta é a minha DLL"));
	return varGlobal;
}

double geraAleatorio(int valor_min, int valor_max)
{
	static int n_vezes = 1;
	if(n_vezes == 1)
	{
		srand(time(NULL));
		n_vezes++;
	}
	return rand() % (valor_max - valor_min) + valor_min;
}
#pragma once
//header.h
//diretivas para o importar e para o exportar
//SO2F3DLL_EXPORTS é uma constante que fou ter que partilhar e vai para o .c
//#ifdef SO2F3DLL_EXPORTS
#ifdef _WINDLL
#define DLL_IMP_API __declspec(dllexport)
#else
#define DLL_IMP_API __declspec(dllimport)
#endif

//porque quero que outros usem, e tem que ser exportado
DLL_IMP_API double varGlobal; //não vai ser exportada

int varInternaDLL;

double geraAleatorio(int valor_min, int valor_max);

DLL_IMP_API double aplicarFactor(double argumento);

e fica criada uma DLL

 

Tags : , , ,