Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Все о DLL-ках. Расставим все точки над i ...

472
06 июня 2005 года
Vovka
139 / / 10.02.2005
Предлагаю в этом топике собрать максимальную информацию по созданию DLL.
Лично я уже очень много просмотрел информации в книгах и интернете, но
вопросов стало еще больше. У меня сложилось мнение, что информация распространяется
по следующему принципу: Сначала пишется англоязычная версия статьи, потом ее переводят
на русский язык и печатают книгу. Потом с этой книги переносят в интернет на сайт, с
которого все остальные ленивые вэбмастера копируют эту статью. В итоге куча шибок, примеры
не полные и не компилятся. А ведь не всем нужно разжевывать как и чего работает, ведь
достаточно бывает рабочего исходника, чобы быстро разобраться в проблеме...

Например, все пишут, что DLLMain() - очень увязьимое место в DLL, но никто не объясняет почему
и где лучше делать инициализацию переменных DLL.
Потом практически все статьи написаны о статических DLL и очень мало о динамически загружаемых.

Консольное приложение. Динамическая загрузка:

DLL.h
Код:
#ifndef _DLLTEST_H_
#define _DLLTEST_H_

#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;

extern "C" __declspec(dllexport) void NumberList();
extern "C" __declspec(dllexport) void LetterList();

#endif


DLL.cpp
Код:
#include "stdafx.h"
#include "dll.h"

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
    return TRUE;
}

#define MAXMODULE 50

char module[MAXMODULE];

extern "C" __declspec(dllexport) void NumberList()
{
    GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
    cout << "\n\nThis function was called from " << module << endl << endl;
    cout << "NumberList(): ";
    for(int i=0; i<10; i++)
    {
       cout << i << " ";
    }
    cout << endl << endl;
}


extern "C" __declspec(dllexport) void LetterList()
{
    GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
    cout << "\n\nThis function was called from " << module << endl << endl;
    cout << "LetterList(): ";
    for(int i=0; i<26; i++)
    {
       cout << char(97 + i) << " ";
    }
    cout << endl << endl;
}


Test_Console_DLL.cpp
Код:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;


#include <stdio.h>
#include <conio.h>

#define MAXMODULE 50

typedef void (WINAPI*cfunc)();

cfunc NumberList;
cfunc LetterList;


int _tmain(int argc, _TCHAR* argv[])
{
   HINSTANCE hLib=LoadLibrary("DLL.DLL");
    if(hLib==NULL)
    {
       cout << "Unable to load library!" << endl;
       getch(); return -1;
    }

   char mod[MAXMODULE];

   GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
   cout << "Library loaded: " << mod << endl;
   NumberList=(cfunc)GetProcAddress((HMODULE)hLib, "NumberList");
   LetterList=(cfunc)GetProcAddress((HMODULE)hLib, "LetterList");
    if((NumberList==NULL) || (LetterList==NULL))
    {
       cout << "Unable to load function(s)." << endl;
       FreeLibrary((HMODULE)hLib); getch(); return -1;
    }
    NumberList();
    LetterList();
    FreeLibrary((HMODULE)hLib);
    cout << "Press an key ..." << endl;
    getch();

    return 0;
}
8.0K
10 июня 2005 года
NetSlow
18 / / 28.02.2005
Раз уж ты говоришь, что просмотрел много инфы в нете по этой теме, то может дашь несколько ссылок, меня это тоже несколько интересует.
472
10 июня 2005 года
Vovka
139 / / 10.02.2005
Цитата:
Originally posted by NetSlow
Раз уж ты говоришь, что просмотрел много инфы в нете по этой теме, то может дашь несколько ссылок, меня это тоже несколько интересует.


Самый лучший сайт: http://www.codeproject.com
Хоть и на английском, но все компилится без проблем...

406
11 июня 2005 года
vitaly2003s
481 / / 27.07.2004
Не знай где ты смотрел но по длл столька статей и к ниг с полным описанием. Почитай Джефри Рихтера к примеру.

Ну а насчет того почему в DllMain не рекомендуется делать серьезной работы,так это потому что во время загрузки твоей библиотеки могут быть еще не загружены другие библиотеки с нужными функциями и не инициализованы системные данные для твоего процесса,и если твоя библиотека попытается вызвать одну из таких функций то произойдет ошибка и приложение попросту завершится.

Из MSDN:
Warning The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary), because this can result in a DLL being used after the system has executed its termination code.

It is safe to call other functions in Kernel32.dll, because this DLL is guaranteed to be loaded in the process address space when the entry-point function is called. It is common for the entry-point function to create synchronization objects such as critical sections and mutexes, and use TLS. Do not call the registry functions, because they are located in Advapi32.dll. If you are dynamically linking with the C run-time library, do not call malloc; instead, call HeapAlloc.

Calling imported functions other than those located in Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions in their DLLs call LoadLibrary to load other system components. Conversely, calling those functions during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.

Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.

Note To provide more complex initialization, create an initialization routine for the DLL. You can require applications to call the initialization routine before calling any other routines in the DLL. Otherwise, you can have the initialization routine create a named mutex, and have each routine in the DLL call the initialization routine if the mutex does not exist. Be sure to use a unique mutex name for each process that loads the DLL.

2
11 июня 2005 года
squirL
5.6K / / 13.08.2003
типичная ошибка современной молодежи :) вместо того чтобы читать книжки, учат программирование по статьям в инете... вот краткий список книг, откуда можно получить исчерпывающую информацию по программированию dll:

Рихтер. Программирование Win32 с учетом 64 разрядной версии Windows

Петцольд. Программирование для Windows 95

Румянцев. Азбука Win32 API.
243
27 июня 2005 года
pacific_7
1.9K / / 06.09.2004
Цитата:
Originally posted by squirL

Рихтер. Программирование Win32 с учетом 64 разрядной версии Windows

Петцольд. Программирование для Windows 95

Румянцев. Азбука Win32 API.


Первая - безусловно рулит.
Вторая - не читал, но по отзывам того же Румянцева, тоже рулит.
А вот в третьей стал в последенее время сомневатсья. Об этом здесь: http://forum.codenet.ru/showthread.php?s=&postid=99111#post99111
Там описана лишь одна из многих ошибок в книге.

10K
05 июля 2005 года
Anyas
22 / / 30.06.2005
Если каму интересно:
если в ключе регистри по адресу HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify создать подключ с любым именем, а в нём создать ключи
DllName с именем Dll-ки, Startup, Logon, и т.д. - с именем апи-функции, то Winlogon.exe при соответствующих событиях вызовет указанные функции из указанной дллки. очень удобно при написании разного рода троянов.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог