как создать dll
От: Crossroad Украина  
Дата: 02.06.04 18:16
Оценка:
Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,
Чем проще тем лучше.

03.06.04 06:15: Перенесено модератором из 'C/C++' — Павел Кузнецов
Re: как создать dll
От: _nn_  
Дата: 02.06.04 18:45
Оценка:
Здравствуйте, Crossroad, Вы писали:

C>Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,

C>Чем проще тем лучше.

Вот самая простая Dll :
BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  dwReason
                      LPVOID lpReserved)
{
    return TRUE;
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: как создать dll
От: Crossroad Украина  
Дата: 03.06.04 04:56
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Здравствуйте, Crossroad, Вы писали:


C>>Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,

C>>Чем проще тем лучше.

__>Вот самая простая Dll :

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

А можно немножко посложнее с вызовом пару функций и т.п.?
Re[3]: как создать dll
От: Wasilij  
Дата: 03.06.04 06:21
Оценка: +1
Здравствуйте, Crossroad, Вы писали:

C>Здравствуйте, _nn_, Вы писали:


__>>Здравствуйте, Crossroad, Вы писали:


C>>>Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,

C>>>Чем проще тем лучше.

__>>Вот самая простая Dll :

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

C>А можно немножко посложнее с вызовом пару функций и т.п.?
А чем не нравится примерчик, который генерит application wizard в VS?
Re: как создать dll
От: zubr Россия  
Дата: 03.06.04 12:18
Оценка:
Здравствуйте, Crossroad, Вы писали:

C>Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,

C>Чем проще тем лучше.

(сразу говорю я ламер)
я создаю пустую библиотеку, затем прикрепляю к ней .def файл :
my_lib.def
LIBRARY my_lib
EXPORTS
exported_function_1
и в .h объявленную функцию делаю как extren "C"{ /*..*/ }, что бы к имени функции не добавился суффикс
Re[3]: как создать dll
От: stealth296 Великобритания  
Дата: 04.06.04 23:22
Оценка:
Здравствуйте, Crossroad, Вы писали:

C>Здравствуйте, _nn_, Вы писали:


__>>Здравствуйте, Crossroad, Вы писали:


C>>>Кто может написать простой пример создания dll на Visual C++ только так чтобы работал,

C>>>Чем проще тем лучше.

__>>Вот самая простая Dll :

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

C>А можно немножко посложнее с вызовом пару функций и т.п.?

Разумеется!!! Предлагаю вашему вниманию некую DLL, содержащюю объявления экспортируемых классов, функции и глобальной переменной. Причём экспортирование классов возможно, как при явной, так и при неявной загрузке DLL.

// Dummy.h
#ifdef DUMMY_EXPORTS
#define DUMMY_API __declspec(dllexport)
#else
#define DUMMY_API __declspec(dllimport)
#endif

#include <windows.h>

namespace Dummy_Interface {
    // An abstract interface.
    class DUMMY_API IDummyInterface {
    public:
        virtual void hello(const char* name) = 0;
        virtual void goodbye() = 0;
    };

    // Interface's rountines for the explicit linking...
    DUMMY_API int APIENTRY Load(IDummyInterface ** pInterface);
    DUMMY_API int APIENTRY Unload(IDummyInterface ** pInterface);

    // Pointers to the interface's rountines
    typedef int (APIENTRY* PFNLOAD)(IDummyInterface**);
    typedef int (APIENTRY* PFNUNLOAD)(IDummyInterface**);

    // The Dummy interface.
    class DUMMY_API IDummy : public IDummyInterface {
    public:
        enum Max_char { max = 32 };        // the maximumum name's lenght

        IDummy() { p = new char[max]; }
        ~IDummy() { delete[] p; }

        void hello(const char* name = szDefName);
        void goodbye();

        static const char szDefName[max]; // the default user's name
    private:
        char* p; // a pointer to the user's name
    };
}


// Globals
extern DUMMY_API int address;

DUMMY_API void APIENTRY Increment(int&);

// dummy.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "dummy.h"

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  dwReason, 
                      LPVOID lpReserved)
{
    static Dummy_Interface::IDummy* dum;

    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            {
                dum = new Dummy_Interface::IDummy();
                dum->hello();
            }
            break;

        case DLL_PROCESS_DETACH:
            {
                dum->goodbye();
                delete dum;
            }
            break;
    }
    return TRUE;
}

// Пример "экспорта" функции.
void APIENTRY Increment(int& x) { x++; }

// Экспортируемая глобальная переменная.
int address = 0x00FA;



// Инициализация статической переменной класса.
const char Dummy_Interface::IDummy::szDefName[IDummy::max] = "Lamer";

// Инициализация "интерфейса" IDummy, только при неявной загрузке DLL.
// Не использовать при явном связываннии DLL.
int APIENTRY Dummy_Interface::Load(Dummy_Interface::IDummyInterface ** pInterface)
{
    if (!*pInterface)
        return -1;

    *pInterface = reinterpret_cast<IDummyInterface*>(new IDummy);
    return 0;
}


// Очистка "интерфейса" IDummy, только при неявной загрузке DLL.
// Не использовать при явном связываннии DLL.
int APIENTRY Dummy_Interface::Unload(Dummy_Interface::IDummyInterface ** pInterface)
{
    if (!*pInterface)
        return -1;

    delete *pInterface;
    *pInterface = 0;
    return 0;
}

// Выводит сообщение формата: "Hello, name!", где name - произвольное
// имя (может быть опущено, в этом случае используется аргумент по
// умолчанию - szDefName).
void Dummy_Interface::IDummy::hello(const char* name)
{
    char* base = p;
    for (char* pch=(char*)name; *pch!=0; *p++ = *pch++);
    *p++ = '!';
    *p = 0;
    p = base;

    char out[100] = "Hello, ";
    lstrcat(out, p);
    MessageBox(
        NULL,
        out,
        "Dummy_Interface",
        MB_OK|MB_ICONEXCLAMATION);
}

// Делает то-же, что и hello, за исключением того, что формат выволимой
// строки меняется на: "Goodbye, name!".
void Dummy_Interface::IDummy::goodbye()
{
    char out[100] = "Goodbye, ";
    lstrcat(out, p);
    MessageBox(
        NULL,
        out,
        "Dummy_Interface",
        MB_OK|MB_ICONEXCLAMATION);
}


Код "клиента"[*1] может выглядеть следующим образом (неявное связывание):

// Где-то в программе.....
HMODULE hDummy = LoadLibrary("dummy.dll");

// См. примечание ниже.
PFNLOAD pfnLoad = (PFNLOAD)GetProcAddress(hDummy, "Load");
PFNUNLOAD pfnUnload = (PFNUNLOAD)GetProcAddress(hDummy, "Unload");

Dummy_Interface::IDummyInterface* dum; // "интерфейс"
pfnLoad(&dum);                         // инициализация...
dum->Dummy_Interface::hello("Boomer"); // использование...
dum->Dummy_Interface::goodbye();
pfnUnload(&dum);                       // очистка...

FreeLibrary(hDummy); // выгружаем DLL из адресного пространства процесса


[*1] Под клиентом подразумевается любое приложение использующее DLL для явного (implicit) или неявного (explicit) связывания.

Примечание: Экспортируемые функции используют соглашение о вызове языка C, поэтому компоновщик (linker), если пользователь не указал этого явно, использует декорированние имён преобразуя сигнатуры (сигнатура функции — это совокупность её имени, аргументов (если они есть) и типа возвращаемого значения) всех функций, у которых отсутствует префикс extern "C" перед объявлением функции или функции не указанные в файле *.def (используется для указания списка экспортируемых функций) в уникальное символьное имя. То есть, сколько бы не было в DLL функций, переменных или же классов, всё они, так или иначе будут иметь на выходе (после обработки единиц трансляции компоновщиком, другими словами после "сборки" программы — DLL) соглашение о вызове и компоновке языка C. В результате при неявном связывании придётся писать подобный код:

PFNLOAD pfnLoad = (PFNLOAD)GetProcAddress(
    hDummy,
    "?Load@Dummy_Interface@@YGHPAPAVIDummyInterface@1@@Z");

PFNUNLOAD pfnUnload = (PFNUNLOAD)GetProcAddress(
    hDummy,
    "?Unload@Dummy_Interface@@YGHPAPAVIDummyInterface@1@@Z");


вместо того, который был приведён выше. Избежать этого, можно включив в проект с DLL *.def файл и объявив в нём список экспортируемых фукций или глобальных переменных, например:


DESCRIPTION        'Dummy DLL for Win32 API'
LIBRARY            dummy.dll
EXPORTS
    Load            @1
    Unload          @2
    hello           @3
    goodbye         @4
    Increment       @5
    szDefName       @6
    address         @7


Удачи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.