Исходник Library class

Статус
В этой теме нельзя размещать новые ответы.

SR_team

like pancake
Автор темы
BH Team
4,809
6,487
Написали с FYP'ом враппер для работы с библиотеками недавно, но мне все стыдно было его выкладывать, и вот сейчас я вроде как готов им поделиться, так что хватайте, пока не удалил.

Основная фичатость враппера - более удобное взаимодействие с библиотеками.
Бонусная плюшка - кроссплатформенность и кросскомпиляторность.

Теперь подробнее и интереснее.
Создавая экземпляр враппера можно не дописывать у названия библиотеки расширение - враппер сам его допишет в соответствии с платформой.

У враппера перегружены операторы [] и (), для подтягивания символов библиотек (аля GetProcAddress). Работают они примерно одинаково, только () указывает, что импортируемая функция имеет тип __stdcall.

Есть пара методов.
name() - возвращает чистое имя библиотеки (без пути и с расширением).
path() - возвращает путь к библиотеке, если он был указан в конструкторе.
handle() - возвращает указатель на адресное пространство библиотеки (аля GetModuleHandle).
hasSuccess() - возвращает инфу о наличии ошибок в загрузке библиотеки.
error() - возвращает ошибку в виде сообщения (т.е. она сразу прямым текстом вам напишет, что ей не нравится).

Где-то тут вы должны меня упрекнуть в оформлении документации, сославшись на то, что всё написанное выше - невнятная хуйня. По этому ниже рассмотрим примеры юзания.

Пример 1. Из своей либы тащим свою функцию:
C++:
#include <iostream>
#include <conio.h>
#include "Library.h"
// Инициализируем враппер как глобальную переменную.
Library lib = "libtest.dll";

int main()
{
    std::cout << "Hello world" << std::endl;

    // Проверяем, все ли хорошо загрузилось
    if (!lib.hasSuccess()) {
        std::cout << lib.error() << std::endl; // Если были ошибки, то выводим их
        _getch();
        return 1;
    }

    // Находим __cdecl функцию getTest
    std::function<int(int)> f = lib["getTest"];
    // Запускаем найденную функцию с аргументом 10 и сразу же выводим результат
    std::cout << f(10) << std::endl;

    _getch();
    return 0;
}
Вывод:
Код:
Hello world
100
Пример 2. Оставим код из примера 1, но удалим нашу библиотеку.
Вывод:
Код:
Hello world
The specified module could not be found.
Id: 126
Пример 3. Изменим код - подсосем системную библиотеку и вызове из нее __stdcall функцию
C++:
#include <iostream>
#include <conio.h>
#include "Library.h"
Library lib = "kernel32.dll";

int main()
{
    std::cout << "Hello world" << std::endl;

    if (!lib.hasSuccess()) {
        std::cout << lib.error() << std::endl;
        _getch();
        return 1;
    }

    // Обрати внимание невнимательный читатель! Скобки теперь круглые, это значит что функция будет иметь тип __stdcall.
    std::function<int()> f = lib("GetTickCount");
    std::cout << "Minutes after start the system: " << f() / 60000 << std::endl;

    _getch();
    return 0;
}
Вывод:
Код:
Hello world
Minutes after start the system: 17
Пример 4. Сравним наш враппер с HMODULE, а так же вызовем метод handle()
C++:
#include <iostream>
#include <conio.h>
#include <assert.h>
#include "Library.h"
Library lib = "kernel32.dll";

int main()
{
    std::cout << "Hello world" << std::endl;

    if (!lib.hasSuccess()) {
        std::cout << lib.error() << std::endl;
        _getch();
        return 1;
    }

    // Получаем HMODULE
    HMODULE kernel32 = GetModuleHandleA("kernel32.dll");

    // Сравниваем враппер с HMODULE
    assert(lib == kernel32);
    // Сравниваем Library::handle с HMODULE
    assert(lib.handle() == (void*)kernel32);

    // Если одно из сравнений в assert вернуло false, то вывода времени работы системы не будет
    std::function<int()> f = lib("GetTickCount");
    std::cout << "Minutes after start the system: " << f() / 60000 << std::endl;

    _getch();
    return 0;
}
Вывод:
Код:
Hello world
Minutes after start the system: 26
Пример 5. Срань (потому что без комментов) на линуксе.
C++:
#include <iostream>
#include "Library.h"
Library lib = "./libtest";

int main(int argc, char **argv) {
    std::cout << "Hello, world!" << std::endl;
   
    if (!lib.hasSuccess()){
        std::cout << lib.error() << std::endl;
        return 1;
    }
   
   
    std::function<int(int)> f = lib["getTest"];
    std::cout << f(17) << std::endl;
   
   
    std::cout << lib.name() << std::endl;
    std::cout << lib.path() << std::endl;
   
   
    return 0;
}
Вывод:
Код:
Hello, world!
289
libtest.so
./
Пример 6. Срань с линукса на винде (в код добавлен _getch() что бы консолька не закрывалась, а в остольном точно такой же)
C++:
#include <iostream>
#include <conio.h>
#include "Library.h"
Library lib = "./libtest";

int main(int argc, char **argv) {
    std::cout << "Hello, world!" << std::endl;

    if (!lib.hasSuccess()) {
        std::cout << lib.error() << std::endl;
        _getch();
        return 1;
    }


    std::function<int(int)> f = lib["getTest"];
    std::cout << f(17) << std::endl;


    std::cout << lib.name() << std::endl;
    std::cout << lib.path() << std::endl;


    _getch();
    return 0;
}
Вывод:
Код:
Hello, world!
289
libtest.dll
./
Пример 7. Возвращаемся к срани на линуксе, но теперь удаляем нашу либу (что бы показать какие ошибки там). Код из 5 примера.
Вывод:
Код:
Hello, world!
./libtest.so: cannot open shared object file: No such file or directory
 

Вложения

  • LibraryClass.zip
    2 KB · Просмотры: 42
  • Нравится
Реакции: BlackKnigga и iAmerican
Статус
В этой теме нельзя размещать новые ответы.