понедельник, 30 августа 2010 г.

Как создать DLL с функциями

Для того чтобы создать динамическую библиотеку в Visual Studio, нужно сначала создать проект: File -> New Project -> Visual C++ -> Win32 Console Application, задать имя проекта (например MyLibrary1) и нажать OK. В появившемся диалоге, на вкладке Application Settings выбрать DLL как тип приложения (Application type). Чтобы создать пустой проект, нужно поставить галочку Empty Project. После этого нажать Finish.
Если галочка Empty Project, при создании проекта, не была поставлена, то будут созданы все необходимые файлы.
Если галочка Empty Project была поставлена, то проект будет пустым и в него, вручную, нужно добавить необходимые файлы. Самый простой вариант, это добавить один файл C++ (Project -> Add New Item -> C++ File (.cpp)) с именем проекта (в нашем случае MyLibrary1.cpp). В него поместить следующий код:
#include <windows.h>
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}

Функции, которые должны быть видимыми для внешних программ, можно поместить в этом же файле, как написано в примере ниже:
extern "C" {
__declspec(dllexport) int func() {
return 0;
}
}

В приведенном выше примере:
Строка 1: Указывает компилятору, что функция именуется в стиле C (убирается декорирование С++, описывающее аргументы функции).
Строка 2: __declspec(dllexport) указывает компилятору, что функция должна быть видима внешним программам.
Также, будет полезно добавить в проект DEF-файл, содержащий описание экспортируемых функций:
LIBRARY "MyLibrary1"
EXPORTS
func

Скомпилируйте проект. Если сделано все как написано, то проблем с дальнейшим импортом функций из библиотеки не возникнет.

Простейшая реализация оператора new

Самая простая пользовательская реализация оператора new, соответствующая всем требованиям стандарта, может выглядеть так:
#include <new>
#include <cstdlib>
void* operator new(std::size_t size) throw(std::bad_alloc) {
if (size == 0)
size = 1;
while (true) {
void* ret = std::malloc(size);
if (ret != 0)
return ret;
std::new_handler handler = std::set_new_handler(0);
if (handler != 0) {
std::set_new_handler(handler);
(*handler)();
}
else
throw std::bad_alloc();
}
}

Строка 1-2: Включение необходимых файлов.
Строка 3: Оператор new может вызывать только исключение std::bad_alloc.
Строки 4-5: Оператор new должен корректно отрабатывать выделение нулевого количество байт.
Строка 6: Выделение памяти и вызов функции-обработчика, в случае невозможности выделения памяти, должны выполняется внутри бесконечного цикла.
Строка 7: Выделение памяти.
Строки 8-9: Если выделение памяти прошло успешно, оператор new возвращает указатель на нее.
Оператор new в случае невозможности, по какой-либо причине, выделения нужный объем памяти, вызывает функция-обработчик, если она задана или вызывает исключение std::bad_alloc(), если она не задана.
Строка 10: Получение указателя на функцию-обработчик.
Строка 11-13: Если функция-обработчик задана, оператор new вызывает его.
Строка 15-16: Если функция-обработчик не задана, оператор new вызывает исключение std::bad_alloc().
Исходный код примера здесь.