Автор: cheops (28.01.2012 в 10:09)
В общем да, в имеется две стратегии: связывание на этапе построения, когда вы добавляете DLL-библиотеку в проект или динамическое связывание во время работы программы. Именно для последнего случая предназначена LoadLibrary(), да собственно и сами DLL-библиотеки. Там не то чтобы сложно - "этикету" больше, но если один раз разобраться - потом не "страшно" :)))
Я так понимаю, с созданием DLL-библиотеки проблем не возникает? На всякий случай я приведу код простейшей библиотеки с одной функцией, HelloWorld(), которая этот самый "Hellow world" и выводит.
#include <Windows.h>
#include <iostream>
using namespace std;
// Главная функция
BOOL WINAPI DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) void HelloWorld(void)
{
cout << "Hello world" << endl;
} |
Главная функция DllMain() практически пустая, события не обрабатываются, нам не надо, так как у нас нет никакой динамической памяти, параллельных потоков и прочего. Теоретически можно вообще DllMain() не создавать - она должна добавляться автоматически компилятором. Функция HelloWorld() объявлена без параметров и возвращаемых результатов, но можно и с тем и с другим - никаких сложностей не возникает. Чтобы функцию было "видно" из вне, она объявляется с атрибутами extern и __declspec(dllexport), "C" - это порядок чтения аргументов, у нас тут их вообще нет, но приводим для единообразия.
Вообще если вы находитесь в VisualStudio, лучше в рамках одного решения создать два проекта - один с DLL-библиотекой, другой - с кодом, тестирующим эту библиотеку. Первый проект понятно DLL, второй - можно консольный. Исполняемым (выделенным жирным) у вас должен быть консольный проект, ему же кстати можно добавить зависимость от DLL-проекта, тогда никаких проблем вообще быть не должно - сначала будет компилироваться DLL, а потом консольный проект.
При условии, что DLL-проект называется dll, а библиотека на выходе соответственно dll.dll, консольный проверочный проект может выглядеть следующим образом
#include <Windows.h>
#include <iostream>
#include <tchar.h>
using namespace std;
int main()
{
// Дескриптор DLL-библиотеки
HMODULE hDll;
// Указатель на функцию
void (*dllHelloWorld) (void);
// Загружаем динамически подключаемую библиотеку
hDll = LoadLibrary(_T("dll.dll"));
if(!hDll)
{
cout << _T("Динамическая библиотека не загружена") << endl;
return GetLastError();
}
// Настраиваем адрес функции
dllHelloWorld = (void (*)(void))GetProcAddress(hDll, "HelloWorld");
if(!dllHelloWorld)
{
cout << _T("Ошибка получения адреса функции") << endl;
return GetLastError();
}
// Вызываем функцию из библиотеки
dllHelloWorld();
// Отключаем библиотеку
if(!FreeLibrary(hDll))
{
cout << _T("Ошибка выгрузки библиотеки из памяти") << endl;
return GetLastError();
}
// Устанавливаем паузу перед завершением программы
system("pause");
return 0;
} |
PS Все проекты в UNICODE, т.е. строки обрамляем макросом _T, если программе нужны параметры, вместо main() используем _tmain(). Кстати, обратите внимание, что GetProcAddress() принимает обычные 8-битные строки, поэтому если у вас названия функций в LPTSTR/LPCTSTR-строках, придется переводить.