Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

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

#cpp #dll


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


Ответы

Ответ 1



Т.е., простыми словами, что вы хотите сделать (вернее, что у вас получится) - вы сохраняете указатель на функцию, выбрасываете из памяти код функции, оставляя указатель непонятно куда, и вызываете ее... Как вы думаете, что у вас получится? std::function тело функции никоим образом не сохраняет. Ну, а указатель на функцию будет инвалидирован вызовом FreeLibrary. Набросать соответствующий код очень просто, можете убедиться сами... indll.cpp #include #include using namespace std; extern "C" void __declspec(dllexport) inDll() { cout << "From DLL\n"; } Компилируем как cl /LD indll.cpp test.cpp #include #include #include #include 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 f = ptr; f(); FreeLibrary(dll); } } Компилируем как cl test.cpp Запускаем test.exe, убеждаемся, что все работает. Меняем местами строки f(); FreeLibrary(dll); компилируем и убеждаемся окончательно, что так поступать нельзя :)

Ответ 2



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

Ответ 3



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

Комментариев нет:

Отправить комментарий