0

У меня есть функция с определенным количеством параметров. Но мне нужно избегать в теле функции обращение к любому параметру:

void MyClass::MyMethod(int32 parm1, FString parm2, UObject* parm3)
{
   void* firstParmPtr = ?;  // как мне получить указатель? Где находится адрес первого параметра?
}

Значение указателя firstParmPtr должно быть равно &parm1.

Нашел интересный момент. Аргументы находятся в стеке, как и новые переменные. Таким образом я могу определить одну переменную в теле функции и вычесть размер всех аргументов функции (есть способ это сделать).

void MyClass::MyMethod(int32 parm1, FString parm2, UObject* parm3)
{
   uint64 _framePtr;
   UFunction* func = FindFunction("MyMethod");
   void* firstParmPtr = &_framePtr - func->ParamsSize;  // Вроде оно...
}

Однако этот вариант не работает. _framePtr слишком далеко в стеке от списка параметров. На много больше чем sizeof каждого параметра. Тогда как мне действовать? Может нужно вычесть ещё какую-то константу?

Нужна любая информация об этом. А так же интересен адрес возвращаемого значения. А ещё желательно без использования ассемблерных вставок. Хотя можно и их, но это не главный объект интереса, так-как я не смогу такое компилировать.

Broly
  • 131
  • Кое-какая информация есть в этом ответе. Вообще, все тут зависит от архитектуры компа. Уточните архитектуру и поточнее сформулируйте конечную цель, может и разберемся. – avp Jan 26 '17 at 21:57
  • Вы, я надеюсь, понимаете, что оптимизатор не то, что может просто заинлайнить вашу функцию, он может вообще выкинуть её вычисление, если сможет доказать, что её результат никому не интересен? – VladD Jan 26 '17 at 23:02
  • Ответ: никак не получить. Откуда вообще могла возникнуть такая идея? С чего вы взяли, что аргументы находятся в стеке? – AnT stands with Russia Jan 27 '17 at 01:33
  • На AMD64 и ARM часть параметров передаётся через регистры. – maestro Jan 27 '17 at 03:50
  • 2
    Между прочим, вы совсем забыли о параметре this. А теперь, если можно - самый главный вопрос - зачем? Это вопрос всерьез, потому что, может, вы просто спрашиваете, как правильно держать микроскоп, чтобы забивать гвозди, а правильно было бы спросить - как гвозди забивать? Может, ваша основная задача решается как-то совсем иначе? – Harry Jan 27 '17 at 04:06
  • Вопрос, возникающий чуть ли не в каждой фразе сообщения - "зачем?". – αλεχολυτ Jan 27 '17 at 06:00
  • @Harry, у меня есть два контекста, где есть функции с одинаковой сигнатурой. Работаю я во фреймворке Unreal Engine 4 (есть рефлексия). И так получается, что одна функция в одном контексте должна вызывать функцию с такой же сигнатурой в другом. Я не хочу вручную копировать названия параметров, (делать нечто вроде этого: void func(int a) { otherObj->func(a); }). Я могу найти функцию по её имени через __FUNCTION__ и систему рефлексии (поиск метода), и я могу вызвать её используя данные в памяти через указатель как аргументы. Осталось придумать как получить указатель на эти данные. – Broly Jan 27 '17 at 08:43
  • @avp, так как это кроссплатформенный фреймворк, мне важно, чтобы это работало на любой архитектуре. Возможно используя какие-то директивы для разных архитектур... – Broly Jan 27 '17 at 08:47
  • Кроссплатформенно, да еще без ограничений (точнее указаний как надо делать) на оптимизацию, точно не сделать. – avp Jan 27 '17 at 09:25
  • Что же касается вашего дополнительного описания в комментарии, то я так и не понял, почему передаваемые в выбираемую функцию (одну их двух) аргументы вам в точке вызова не известны? (имена переменных или их адреса). Впрочем, поскольку у вас С++, то наверное основная проблема с моделированием this? – avp Jan 27 '17 at 09:32
  • Мда... Сигнатуры вам доступны? Вы можете менять код? Может, тогда объединять все параметры в одну структуру, и передавать ее? Но, как по мне, то искать функцию по имени, и пытаться передавать через указатель параметры - это уже что-то запредельно сложное... Кроме того, как я понимаю, вы хотите передать вызываемой функции ее параметры не в новом фрейме стека, а прямо в старом? Вы уверены, что эта овчинка стоит выделки? – Harry Jan 27 '17 at 10:04
  • @avp, не очень понимаю каким боком тут this. Он как параметр-указатель занимает 8 байт в текущем фрейме. Верно? Однако там гораздо больший отрыв локальной переменной до параметров, чем 8 байт. Да, кроссплатформенно, быть может директивами компилятору сделать несколько вариантов для разных архитектур. У меня даже скорее больше академический интерес, нежели практический. Аргументы известны. Они нужны для генерации кода и рефлексии UE4, но для меня они формальность (нечто вроде эллипсиса: ..., но без предшествующего параметра). – Broly Jan 27 '17 at 11:07
  • @Harry, сигнатуры доступны. Рефлексивная информация о функции есть. Код менять в реал-тайме не могу. Почему же сложное? Возможно не совсем типичное для С++, но оно существует во фреймворке как нормальное явление. Да, именно в старом. Я просто хочу передать указатель на эти данные (может быть скопировать предварительно их). Выглядит это примерно так: UFunction* func = FindFunction("FuncName"); ProcessEvent(func, paramsPtr); – Broly Jan 27 '17 at 11:09
  • Если речь зашла о 8 байтах, то давайте конкретно. Про какой комп, ОС и компилятор идет речь? – avp Jan 27 '17 at 11:19
  • @avp, на текущий момент у меня Win64, Intel i7 4820K, Visual Studio. Но потенциально оно будет компилиться и на других ОС (скорее всего не х32), процах и компиляторах (например gcc, clang). – Broly Jan 27 '17 at 11:22
  • Ну, с M$ не хочу ковыряться. – avp Jan 27 '17 at 12:35

0 Answers0