Хранение функции

321
25 февраля 2017, 05:19

Есть указатель на функцию, расположенную в DLL библиотеке. Можно ли эту функцию сохранить в объекте типа std::function<...> при корректном указании шаблонных параметров, затем отключить библиотеку через FreeLibrary (работаю в MSVC) и работать с функцией через std::function? Мне просто надо запихать туда разыменованный указатель на эту функцию?

Answer 1

Т.е., простыми словами, что вы хотите сделать (вернее, что у вас получится) - вы сохраняете указатель на функцию, выбрасываете из памяти код функции, оставляя указатель непонятно куда, и вызываете ее...
Как вы думаете, что у вас получится?

std::function тело функции никоим образом не сохраняет. Ну, а указатель на функцию будет инвалидирован вызовом FreeLibrary.

Набросать соответствующий код очень просто, можете убедиться сами...

indll.cpp

#include <iostream>
#include <iomanip>
using namespace std;
extern "C" void __declspec(dllexport) inDll()
{
    cout << "From DLL\n";
}

Компилируем как cl /LD indll.cpp

test.cpp

#include <iostream>
#include <iomanip>
#include <functional>
#include <windows.h>
using namespace std;
int main(int argc, const char * argv[])
{
    HMODULE dll;
    if (0 != (dll = LoadLibrary("inDll.dll")))
    {
        cout << "Load success\n";
        FARPROC ptr = GetProcAddress(dll,"inDll");
        function<void(void)> f = ptr;
        f();
        FreeLibrary(dll);
    }
}

Компилируем как cl test.cpp

Запускаем test.exe, убеждаемся, что все работает. Меняем местами строки

        f();
        FreeLibrary(dll);

компилируем и убеждаемся окончательно, что так поступать нельзя :)

Answer 2

Ни в языке С, ни в языке С++ нет понятия "сохранить функцию". Любые манипуляции с std::function или чем-то подобным будут работать только и именно с указателем на оригинальную функцию.

С "разыменованным указателем на функцию" в С++ можно сделать только весьма ограниченное количество вещей: например, вызвать функцию или преобразовать его обратно в указатель. "Запихать" результат разыменования никуда нельзя.

Answer 3

std::function является лишь обёрткой над некоторой сущностью, которую можно вызвать. Если код этой сущности становится недоступен (например, после выполнения FreeLibrary), то попытки вызвать его будут приводить к неопределённому поведению. Скорее всего Вы просто получите некоторую ошибку времени выполнения от операционной системы.

Не стоит считать std::function каким-то волшебным контейнером, который хранит код, и если его куда-то передать, то он может быть выполнен. Иначе можно было бы развить мысль и предположить, что, скажем, упаковка и передача объекта std::function по сети на другое устройство будет допускать возможность выполнить код, "хранимый" в этом объекте. Такое невозможно хотя бы по причине того, что на другом конце сети может быть устройство совершенно иной архитектуры и код (грубо говоря, последовательность команд) должен быть совсем иным. Для обеспечения подобного используются другие технологии, например, CORBA.

READ ALSO
Qt | SQLite и QSqlTableModel

Qt | SQLite и QSqlTableModel

У меня есть таблицаКласс Table, унаследованый от QTableWidget и есть база данных

425
Проблема прокрутки MFC

Проблема прокрутки MFC

Здравствуйте, возникла проблема при подключении полосы прокрутки к окнуВ общем в окне рисуется график, при этом координаты смещаются с помощью...

305
Не могу определить &ldquo;GestureID&rdquo; в условии &ldquo;if&rdquo;

Не могу определить “GestureID” в условии “if”

При компиляции под win64 все работает корректноПри компиляции под Android вылетает ошибка:

253