C ++: динамический вызов виртуальной функции - PullRequest
0 голосов
/ 04 ноября 2010

Я ищу решение для динамического вызова виртуальной функции. Это означает поддержку вызовов функций со смещениями и динамическими типами во время выполнения.

Я работаю над плагином для игры (Counter-Strike: Source, если вы это знаете). Интерфейс плагина маловероятен, и поэтому вы не можете расширять его так, как хочет большинство людей. Чтобы реализовать лучший способ общения и манипулирования игрой, я поддерживаю вызов виртуальных функций. Например, класс CCSPlayer имеет следующие методы:

Offset    Name
...
201       CCSPlayer::Ignite()
...
205       CCSPlayer::CommitSuicide(bool Blah)
...
250       CCSPlayer::SomeFunctionWith2Params(int A1, float A2)

Передав эти смещения и указатель на экземпляр этого класса моей текущей функции (см. Ниже), я могу вызвать следующие функции:

CBasePlayer *pPlayer = Players.Find("mike");
bool bResult = Call2<bool, int, float>(210 /* offset */, pPlayer, 20, 50.0f);

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

А теперь я хочу добавить язык сценариев с динамическими вызовами виртуальных функций. Это означает, что сценаристы могут устанавливать количество параметров и их тип. Затем передаем указатель this и смещение функции, чтобы наконец выполнить ее. Это мои настоящие вопросы.

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

template<typename T, typename A, typename B> T Call2(int iOffset, void *pThis, A arg1, B arg2)
{
    void **pVTable = *(void***)pThis;
    void *pPointer = pVTable[_iOffset]; 

    union
    {
        T (CVCallEmpty::*pCall)(A, B);
        void *pAddress;
    } Data;

    Data.pAddress = pPointer;

    return (reinterpret_cast<CVCallEmpty*>(*(void***)&pThis)->*Data.pCall)(arg1, arg2);
}

Теперь, есть ли возможность поддерживать динамические вызовы?

Ответы [ 3 ]

3 голосов
/ 04 ноября 2010

Это настолько сломано, что трудно подумать о его расширении.

Вы не обрабатываете виртуальное наследование.Вы даже не обрабатываете множественное наследование.

Виртуальная функция не может быть представлена ​​как одно целое число "смещения".Вам необходимо принять аргумент указатель на член.

1 голос
/ 04 ноября 2010

Как сказал другой автор, нативного способа сделать это в C / C ++ нет.

ОДНАКО, вас может заинтересовать библиотека FFCALL , а точнее avcall . Эта библиотека позволяет создавать списки параметров, а затем вызывать на них функции.

0 голосов
/ 05 ноября 2010

Нет встроенного способа генерировать перестановки.Думаю, вы могли бы использовать некоторую библиотеку, но я рекомендую написать небольшую программу для генерации всех шаблонов для вас.Это дает вам полный контроль над тем, какой исходный код генерируется, в нем нет постороннего мусора, и его легко выполнить за один шаг.

Одна из проблем с представленным подходом заключается в том, что типы параметров для функции, на которую указываютвыводится из представленных аргументов;типы параметров действительно должны быть указаны независимо.В его нынешнем виде вы можете (скажем) передать число с плавающей точкой в ​​функцию, ожидающую int, и получить недопустимые результаты (в лучшем случае).Звонящий должен быть очень точным со своими значениями!Если у вас есть программа для генерации исходного кода, вы можете слегка настроить ее для генерации функций пересылки, например:

inline void call_vii(int vi,void *obj,int a0,int a1) {
    Call2<void,int,int>(vi,obj,a0,a1);
}

inline float call_viff(int vi,void *obj,int a0,float a1,float a2) {
    Call2<void,int,float,float>(vi,obj,a0,a1,a2);
}

И так далее, до бесконечности (или не далеко).

Конечно, это не совсем удобно.И это генерирует много функций.Но если вы собираетесь показывать это на языке сценариев, вам все равно понадобится функция для каждой комбинации типов параметров ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...