Форум программистов, компьютерный форум CyberForum.ru

Альтернативный вызов функции - C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.74
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
15.08.2014, 10:44     Альтернативный вызов функции #1
1. Интересует метод вызова функции через указатель(или по другому).
2. Интересует метод взятия кол-ва аргументов функции и их типов, а так же тип возвращяемого значения.

По второму пункту вообще ничего не нашёл, а по первому есть некоторые вопросы.
C++
1
2
3
4
5
6
7
8
9
#include "FTD2XX.h" // библиотека от FTDI
typedef FT_STATUS (*pFT_Open) (int, FT_HANDLE *); // тип данных "функция FT_OPEN"
 
HMODULE hMod = LoadLibrary ("FTD2XX.dll"); // загрузка библиотеки - д. б. не ноль
pFT_Open pOpen = GetProcAddress (hMod, "FT_Open"); // получили адрес функции - также д. б. не ноль
 
FT_STATUS st = pOpen (0, &hDev);    // вызываем функцию
 
FreeLibrary (hMod); // закрыли библиотеку
Нашёл вот такой вот вызов функции через строку названия функции "FT_Open". Меня интересует, если не создавать DLL, то можно ли как то вызвать подобным способом стандартную функцию (например из winuser.h)?

Ещё заинтересовало такое:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int (*cmp) (const char *, const char *));
int main(void)
{
char s1 [80], s2[80];
int (*p) (const char*, const char*);
p = strcmp; /* получение адреса strcmp() */
gets(s1);
gets (s2);
check(s1, s2, p);
return 0;
}
 
void check (char *a, char *b, int (*cmp) (const char *, const char *))
{
printf("Testing for equality.\n");
if(!(*cmp) (a, b)) printf("Equal");
else printf("Not equal");
}
Однако тут явно указывается кол-во членов и их тип :
C++
1
int (*p) (const char*, const char*);
Что мне не подходит, можно как то это преодолеть? И ещё меня не устраивает что надо явно писать:
C++
1
p = strcmp;
А не строковой (char *) переменной, что дало бы возможность динамики (ну именно это в конечном итоге меня и интересует).

П.С. Если это возможно, приводите пожалуйста примеры без использования STL и классов, а более приближенными к Си методами.

Вообще по поводу пункта 2: подумалось, что если реализовать пример1, то нужен будет список функций, который я в принципе могу хранить в txt фале вместе с кол-вом аргументов и возвращяемым значением, хотя это будет тупое копирование строк из .h файлов, к примеру из winuser будут подобия:
C++
1
WINUSERAPI LRESULT WINAPI SendMessageA(HWND,UINT,WPARAM,LPARAM);
От сюда я могу "запарсить" и искомое извлечь для выполнения операции. Не думаю что будет смысл париться над пунктом2, т.к. игра не стоит свеч, значит стаётся открытым вопрос первый.

Добавлено через 29 минут
Узнал что это:
C++
1
typedef FT_STATUS (*pFT_Open) (int, FT_HANDLE *);
являет прототипом функции. В общем вот эту инициализацию прототипа можно обойти? Т.е. подразумеваю что например у меня будет динамический массив с переменными, после парсинга я получу типы, и согласно им - заполню массив. Далее если бы можно было бы реализовать вызов GetProcAddress с сылкой на массив, то хотелось бы чтоб автоматически передавались в аргументы значения массива от [1] и до кол-ва аргументов ( [0] аргумент думаю будет идти как возвращяемое значение функции)... (может как то можно использовать в данном случае переменное кол-во аргументов в функции?)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.08.2014, 10:44     Альтернативный вызов функции
Посмотрите здесь:

C++ Вызов функции
C++ Вызов функции
C++ Вызов функции в C++
C++ Вызов функции!
Вызов функции в возврате значения функции C++
C++ Вызов функции
Вызов функции C++ Builder
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
19.08.2014, 08:17  [ТС]     Альтернативный вызов функции #41
Что то пример который дал StailGot не компилится... на VStudio(2005)

1. Ошибка:
template<typename ...Args>
error C2143: syntax error : missing ',' before '...'
2. Ошибка:
int call( void * fun, Args ... args)
error C2061: syntax error : identifier 'Args'
3. ещё одна в вызове самой функции:
res = call(me, (HWND)NULL, "hi", "message", (UINT)NULL );
error C2780: 'int call(void *)' : expects 1 arguments - 5 provided
Почему так?

Добавлено через 13 минут
Кстати нашёл на MSDN эту тему... http://msdn.microsoft.com/ru-ru/library/dn439779.aspx
но почему же компиляционные ошибки то(

Добавлено через 9 минут
При этом MSDN пишет:
В C++ оператор ... используется в блоках обработки исключений catch, а в C++11 — для шаблонов с переменным числом аргументов.
Типа только в 2011+ версиях будет работать?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6795 / 4006 / 920
Регистрация: 30.01.2014
Сообщений: 6,830
19.08.2014, 09:10     Альтернативный вызов функции #42
Цитата Сообщение от Izual Посмотреть сообщение
Типа только в 2011+ версиях будет работать?
Ага, начиная с VS 2013 или VS 2012 с последним обновлением. Как я уже говорил, это С++11 (действующий стандарт С++), а в VS достаточно инертно добавляют его поддержку (таблица поддержки возможностей на MSDN), в GCC и Clang давно все реализовано.
Кстати на С стандарт тоже обновился и тоже в 2011 году.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
19.08.2014, 10:33  [ТС]     Альтернативный вызов функции #43
Да заработало (установил VS 2013). Только теперь всё же остался вопрос с возвращяемым значением, оно не во всех функциях будет int. Как я понял из void* в int только warning, а вот уже даже с float будет error.
Прототип через шаблон функции, который предложил StailGot можно как то привести к динамическому использованию возвращяемого результата? (чтоб и double, и многие другие работали?)

Добавлено через 20 минут
П.С. Поясню сразу, что таблица с значениями у меня будет, т.е. я буду заранее знать какой тип вводить и выводить.
Например:
WINUSERAPI int WINAPI MessageBoxA(HWND,LPCSTR,LPCSTR,UINT);
HMENU WINAPI LoadMenuA(HINSTANCE,LPCSTR);
WINUSERAPI HWND WINAPI SetActiveWindow(HWND);
Имея такую таблицу, я хотел бы имея структуру (с "вложенными" union и enum) вида:
C++
1
2
3
4
5
6
7
8
9
10
11
12
typedef enum { BOOL,INT,FLOAT,STR } vtr;
struct var
{
    vtr t;//тип переменной
    union
    {
        bool b;
        int i;
        float f;
        char *s;
    }d;//данные переменной
};
просто исходя из типа переменной (v[i].t) задать в функции возвращяемое значение.

Да и ещё меня инетересует, можно ли исходя из типа вызова с помощью каких нибудь директив указывать использование _stdcall, например хотел было сделать так:
C++
1
#define WINAPI _stdcall
Но не работает =)

Добавлено через 5 минут
Подумалось, по пункту возвращяемого значения...
Ведь я могу изменить функцию:
C++
1
int call( vtr v, void * fun, Args ... args)
и в соответствии с типом сделать (что конешно вот меня не радует прототипы вызова для всех возможных возвращяемых значений... Примерно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
switch(v):
{
case INT:
 using func_type = int( _stdcall *)( Args... ); // выведем тип функции по ее аргументам
 return ( (func_type)fun ) ( args... );
break;
case FLOAT:
 using func_type = float( _stdcall *)( Args... ); // выведем тип функции по ее аргументам
 return ( (func_type)fun ) ( args... );
break;
...
}
}
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
19.08.2014, 15:17     Альтернативный вызов функции #44
Izual,
Цитата Сообщение от Izual Посмотреть сообщение
и в соответствии с типом сделать (что конешно вот меня не радует прототипы вызова для всех возможных возвращяемых значений...
Только так скорее всего. Ведь для того, чтобы вызвать функцию нам нужно знать ее тип и если аргументы еще можно вывести неявно, то возвращаемый тип без сигнатуры не узнать.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
19.08.2014, 15:27  [ТС]     Альтернативный вызов функции #45
Цитата Сообщение от ForEveR Посмотреть сообщение
Ведь для того, чтобы вызвать функцию нам нужно знать ее тип и если аргументы еще можно вывести неявно, то возвращаемый тип без сигнатуры не узнать.
Вы не поняли, у меня есть список функций, мне надо упростить вызов, чтоб не писать ~30 разных по возвратному значению прототипов. Я пробовал с void * из предыдущего примера, но void* работает только с <= 32 бита, а это мало, мне надо больше.
Может есть какой то способ динамического приведения типа или что то вроде этого, просто хочется один раз написать прототип и не париться. Я хочу так:
C++
1
2
3
4
5
int call( vtr vtype, void * fun, Args ... args)
{
 using func_type = vtype( _stdcall *)( Args... ); // выведем тип функции по ее аргументам
 return ( (func_type)fun ) ( args... );
}
Чтобы один этот прототип разпростронялся на все виды функций. vtr vtype это и будет конкретный тип, ну у меня в виде enum это сделано, хотя я думаю что это не подойдёт, ну может как то по другому можно..
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
19.08.2014, 16:05     Альтернативный вызов функции #46
Izual, Понял я все. Нет, нельзя так сделать. И через enum не получится, т.к. сигнатура функции ДОЛЖНА быть известна на этапе компиляции. Фича с variadic templates на самом деле тоже работает на этапе компиляции, т.е. когда мы пишем call(fun, args...) мы знаем, что передается некий указатель на void и абсолютно конкретные аргументы, уже на этапе компиляции.

Добавлено через 13 минут
Цитата Сообщение от Izual Посмотреть сообщение
Я пробовал с void * из предыдущего примера, но void* работает только с <= 32 бита, а это мало, мне надо больше.
Можно так же попробовать использовать boost::any или что-нибудь вроде, не знаю получится ли и возможности проверить нет.

C++
1
2
using func_type = boost::any(Args...);
boost::any result = func_type(args...);
И дальше уже либо здесь, либо где-то еще кастуем boost::any к нужному типу.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
19.08.2014, 16:49  [ТС]     Альтернативный вызов функции #47
Не знаю в тему ли, но накапал: http://www.drdobbs.com/cpp/extractin...0000586?pgno=2

Используется Variant... может и в возвращяемое значение его получится сунуть в моём случае?
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
19.08.2014, 17:39     Альтернативный вызов функции #48
Izual, Вряд ли. Единственное, что я могу предложить это работать очень аккуратно через ваш ENUM.
Что-то вроде

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
int call_1() 
{
   std::cout << "This" << std::endl;
   return 0;
}
double call_2() { return 0; }
 
void call(int v, void* f)
{
   switch(v)
   {
   case 1:
      using fptri = int(*)();
      ((fptrd)f)();
      break;
   case 2:
      using fptrd = double(*)();
      ((fptrd)f)();
      break;
   }
}
 
int main()
{
   call(1, (void*)&call_1);
}
Ну или через any/variant и т.д. все так же:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <boost/any.hpp>
 
int call_1() 
{
   std::cout << "This" << std::endl;
   return 0;
}
double call_2() { return 0; }
 
void call(int v, void* f)
{
   using fptr = boost::any(*)();
   ((fptr)f)();
}
 
int main()
{
   call(1, (void*)&call_1);
}
call допустим возвращает boost::any, а вот преобразовывать во что-то более конкретное его уже придется in-place.
DrOffset
6795 / 4006 / 920
Регистрация: 30.01.2014
Сообщений: 6,830
19.08.2014, 22:19     Альтернативный вызов функции #49
Izual, Для настоящей динамики у нас должно быть динамическое окружение. С шаблонами мы так или иначе остаемся в рамках строгой типизации. Т.е. по настоящему динамичен будет только тот самый первый вариант, с VM (Virtual Machine) внутри нашей программы (которую реализует эта библиотека).
Есть высказывание, что "любую задачу можно решить увеличением уровня абстракции, кроме задачи слишком большого числа уровней абстракций". В данном случае именно это и есть единственное решение. Мы вынуждены организовать динамическую систему (новый уровень абстракции, по сравнению с самим языком С++) внутри нашей программы, чтобы она во время работы приложения, обеспечивала нужную нам функциональность - в частности реализовать загрузку допустимых прототипов из файла.

С другой стороны, так ли нужна тебе эта динамика? Может просто ограничиться возможность задания прототипа "по месту", что, собственно, у нас почти получилось? А возвращаемое значение можно и так обыграть:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template<typename R, typename ...Args>
R call(FARPROC fun, Args ... args)
{
    using func_type = R( __stdcall *)(Args...); // выведем тип функции по ее аргументам
    return ((func_type)fun)( args... );
}
 
int main()
{
    char fn[] = "MessageBoxA";
    int res = 0;
    HMODULE hMod = LoadLibraryA ( "user32.dll" );
    if ( !hMod )
        cout << "Library not loaded" << endl;
    else
    {
        FARPROC me = GetProcAddress( hMod, fn );
        if ( !me )
            cout << "Function not loaded" << endl;
        else
        {
            res = call<int>(me, (HWND)NULL, "hi", "message", (UINT)NULL );
            cout << res << endl;
        }
        FreeLibrary ( hMod );
    }
    return 0;
}
Всяческие boost::any - это хорошо, но опять же работать будет только в системе, где это централизованное, общее решение для всех вызовов. Мы не можем просто скастить функцию, которая на самом деле возвращает int к прототипу, который возвращает any. any - это класс, и он должен быть соответствующим образом сконструирован, а волшебным образом в нем не окажется возвращаемое значение, например, записанное в eax функцией из dll.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
20.08.2014, 07:42  [ТС]     Альтернативный вызов функции #50
Цитата Сообщение от DrOffset Посмотреть сообщение
работать будет только в системе, где это..
Вот именно по этому я классы не люблю, такие подводные камни сразу отбивают желание их использовать.

Цитата Сообщение от DrOffset Посмотреть сообщение
res = call<int>(me, (HWND)NULL, "hi", "message", (UINT)NULL );
Так я же не могу динамически изменять "<int>" в соответствии с типом, т.е. мне придётся в ручную прописывать опять же все эти типы вызовов функций.

Кстати тут ещё одна проблема нарисовалась, я как то её "на потом" откладывал, но в итоге она всё же немного помешает. Суть такова, если я хочу динамически передавать аргументы, то явно писать:
C++
1
NULL, "hi", "message", NULL
в общем то тоже не получится, т.к. в результате всё сведётся к подобному:
C++
1
res = call<int>(me, v[1].d.hw, v[2].d.str, v[3].d.str, v[4].d.ui);
но для пременного кол-ва членов придётся писать опять же прототипы по кол-ву аргументов передаваемых значений. Жаль что язык сам не сможет подставить в соответствии с кол-вом аргументов (ну число то у меня будет) их самих... (единственное что я ещё не протестировал это использование оператора чтоб писать без ".str", а напрямую "v[i].d", чем сейчас и займусь)

Добавлено через 8 минут
Кстати а может вместо <int> я могу использовать type_name?
(наткнулся тут на это http://www.cplusplus.com/reference/t...ype_info/name/)
DrOffset
6795 / 4006 / 920
Регистрация: 30.01.2014
Сообщений: 6,830
20.08.2014, 08:33     Альтернативный вызов функции #51
Цитата Сообщение от Izual Посмотреть сообщение
Вот именно по этому я классы не люблю
Тут ты не прав. Таже самая вещь, например, касается int и double. int и double возвращаются из функции разными способами, вызывающая сторона должна знать как именно, иначе она не получит верное значение. Так что тут нет разницы классы или нет, все равно в общем случае нужно будет знать, что это за тип, чтобы правильно его получить. В С++ и С мы должны это знать на этапе компиляции.
А классы - это те же С-структуры, только с возможностью определеять операции для них. Вот например класс
C++
1
2
3
4
5
6
class A
{
public:
    A() {} //init
    ~A() {} // deinit
};
и C-структура:
C++
1
2
3
4
5
struct A
{
};
void init(A * p) {} // init
void deinit(A * p) {} // deinit
разница только в том, что компилятор самостоятельно следит за вызовом init и deinit, вместо ручного вызова в случае с С-структурой. Сами принципы не меняются совершенно.

Цитата Сообщение от Izual Посмотреть сообщение
результате всё сведётся к подобному:
Именно.

Цитата Сообщение от Izual Посмотреть сообщение
Кстати а может вместо <int> я могу использовать type_name?
Нет. Шаблоны - это только время компиляции, динамику они не затрагивают.
С текущим решением дальше этого
Цитата Сообщение от Izual Посмотреть сообщение
res = call<int>(me, v[1].d.hw, v[2].d.str, v[3].d.str, v[4].d.ui);
ты не уйдешь...

Добавлено через 9 минут
Цитата Сообщение от Izual Посмотреть сообщение
я могу использовать type_name?
Опять же, можно построить систему на type_info или на полиморфизме, но для этого нужно чтобы была централизованная поддержка, возвращаемые значения и передаваемые аргументы можно было бы сделать плиморфными типами, с общей базой. И я открою секрет - boost::any использует внутри type_info - поэтому все, что я говорил выше про any, будет верно и для рукопашного решения с type_info: нужна поддержка таких вещей во всей системе централизовано. Т.е. все dll которые планируются использовать - должны оперировать те ме же категориями, тогда все модули друг друга поймут. Общего же решения забесплатно не будет.
Dmitriy_M
1307 / 1188 / 109
Регистрация: 20.03.2009
Сообщений: 4,262
Записей в блоге: 11
20.08.2014, 09:03     Альтернативный вызов функции #52
Так я же не могу динамически изменять "<int>" в соответствии с типом, т.е. мне придётся в ручную прописывать опять же все эти типы вызовов функций.
Кодогенерация? Пишешь скрипт на Python/Perl который бегает по заголовочным файлам и делает обетрку над функциями.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
20.08.2014, 09:41  [ТС]     Альтернативный вызов функции #53
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
скрипт на Python/Perl
Это не вариант... по крайней мере для меня. Я думаю что решение есть, на С++, только те кто знают не говорят)
Цитата Сообщение от DrOffset Посмотреть сообщение
во всей системе централизовано
надо найти центр)))
Что то последние посты меня не вдохновляют, пойду пить йад.
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
20.08.2014, 09:58     Альтернативный вызов функции #54
Izual, Не вдохновляют потому что вы пытаетесь решить проблему на языке не предназначенном для решения этой проблемы. Гвозди тоже можно топором забивать, но зачем, если есть молоток?
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
20.08.2014, 10:48  [ТС]     Альтернативный вызов функции #55
ForEveR, слушайте, мне по поводу первого вопроса тоже говорили тоже самое. Но пришёл StailGot и показал как решить проблему. Не полностью, но это видимо потому что за 3 страницы опять наспамили (ну как обычно пока истину найдёш, куча подводных вопросов и ответов вышло).
Так что я думаю что и из оставшейся задачи тоже есть решение. Я не просто "думаю", я верю, потому что если бы С++ не мог бы решить подобные проблемы, то наверно уже давно бы другие языки были более популярны, а Си бы умер.
Цитата Сообщение от ForEveR Посмотреть сообщение
можно топором забивать
Ответ в многофункциональности, есть и мульти-инструмент, где с одной стороны топорище, а с другой "молотище"
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
20.08.2014, 10:58     Альтернативный вызов функции #56
Izual, С++ используется для решения своих задач. С++ статически-типизированный язык. Проблема использованием variadic-templates не решилась, мы все равно остались в границах этапа компиляции, а не этапа выполнения.
Послушайте DrOffset или Dmitriy_M, либо действительно полностью динамическое окружение (как в интерпретируемых, а не комилируемых языках или же как в языках с виртуальной машиной), либо кодогенерация.
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
20.08.2014, 12:07  [ТС]     Альтернативный вызов функции #57
Цитата Сообщение от ForEveR Посмотреть сообщение
остались в границах этапа компиляции, а не этапа выполнения
Меня это мало волнует. Меня интересует лишь возможность решения моей задачи, способы решения и подводные камни.

Добавлено через 14 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
Послушайте DrOffset или Dmitriy_M
Я слушаю что говорят, многое что было сказано было полезным, хотя бы для ознакомления, так сказать опыт. Но решая задачу, так сказать, и метод реализации очень важен. Победу можно одержать разными путями, и пренебрегать какими то, может и не понятными для других, моментами я не хочу. Я уже вышел за рамки того что я хотел использовать приближенные к старому Си методы, ввиду того что просто невозможно было выполнить искомое, однако изучать ещё 100500 языков не вижу смысла, лучше в этом буду капаться дальше, и возможно решение найдётся.
DrOffset
6795 / 4006 / 920
Регистрация: 30.01.2014
Сообщений: 6,830
20.08.2014, 13:58     Альтернативный вызов функции #58
Цитата Сообщение от Izual Посмотреть сообщение
мне по поводу первого вопроса тоже говорили тоже самое
Ничего из того, что говорили в первых сообщениях, решение StailGot не опровергло. Все решения, в том числе решение StailGot, крутятся вокруг статической типизации. Шаблон - это генератр кода, для разного количества типов или аргументов будет сгенерирован свой код, своя функция call. Вся эта механика работает на этапе компиляции, т.е. мы снова вернулись к статической типизации. В шаблоне в общем случае возвращаемый тип автоматически не вывести, поэтому приходится писать его явно. Еще раз, это очень важно, чтобы ты понял - решение StailGot подчиняется законам статической типизации, работает только на этапе компиляции и в динамике работать не будет.
В языке С++ и С нет такого механизма, который мог бы по известному в динамике списку аргументов положить параметры на стек и вызвать некую процедуру по адресу, а потом по известному в динамике типу возвращаемого значения адекватным образом получить возврат. Просто нет. Этот механизм надо делать. Можно использовать уже готовые решения, навроде того, что я уже предлагал. В принципе - это полностью решает все вопросы, но ты от чего-то это решением не считаешь. Ладно, хорошо. Тогда это можно сделать вручную с использованием встроенного ассемблера или написать отдельный модуль на ассемблере. Естественно работать будет для конкретного компилятора и конкретной платформы, т.к. встроенный ассеблер и вообще ассемблерные инструкции различаются на разных компиляторах и архитектурах соответственно.
Если оставаться только в рамках языка, то любые динамические решения должны быть согласованы во всей системе. Очевидно, что WinAPI ничего не знает ни про any, ни про type_info, т.к. написано на С. И сами функции WinAPI не рассчитанны на динамическую типизацию из коробки, поэтому подчиняются все тем же законам статической типизации и предполагают, что компилятор сгенерирует код по заданному прототипу. Вот если бы функции сразу возвращали плиморфные типы или типы, или что-то вроде твоих union, то тогда можно было бы говорить о каким-то мыслимом обобщении в динамике без участия неязыковых средств.

Теперь я бы хотел вернуться к исходной задаче. Ведь проблема, которую ты пытался этим решить, на самом деле не стоит такого решения. Если бы она стоила такого решения, то это решение давно было бы у всех на виду и все бы им пользовались. Но никто им не пользуется. Но раз уж тебе хочется просто не писать вручную приведение к нужным прототипам, и ты уже согласился на использование С++11, то можно ведь и так поступить и остаться при этом в рамках типизации С++, и не писать ужасных велосипедов на тему динамического вызова:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
template <typename F>
F GetProcAddress(HMODULE hMod, char const * name, F f = FARPROC())
{
    return F(::GetProcAddress(hMod, name));
}
 
#define GetProcAddressProto(hMod, f) \
        GetProcAddress((hMod), (#f), (f))
 
int main()
{
    int res = 0;
    HMODULE hMod = LoadLibraryA("user32.dll");
    if ( !hMod )
        cout << "Library not loaded" << endl;
    else
    {
        // так:
        auto me = GetProcAddressProto(hMod, MessageBoxA);
        // или так:
        //auto me = GetProcAddress(hMod, "MessageBoxA", MessageBoxA);
        if ( !me )
            cout << "Function not loaded" << endl;
        else
        {
            res = me(NULL, "hi", "message", NULL);
            cout << res << endl;
        }
        FreeLibrary ( hMod );
    }
    return 0;
}
Решение строится на том, что прототип и так описан в заголовке winuser и мы можем использовать его для получения типа указателя на функцию. А макрос убирает лишнюю писанину.

auto - это вывод типа переменной в С++11 исходя из возвращаемого выражением значения, в данном случае F в шаблоне функции (в F реальный прототип).
Jupiter
20.08.2014, 14:29
  #59

Не по теме:

еще! еще бисеру насыпьте

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.08.2014, 14:33     Альтернативный вызов функции
Еще ссылки по теме:

Вызов функции в параметре другой функции C++
Функции в Assembler, вызов функции в C++ C++ Builder
C++ Вызов функции внутри другой функции с передачей локальной переменной по ссылке
C++ Вызов функции
вызов функции из под функции C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Izual
 Аватар для Izual
93 / 118 / 6
Регистрация: 13.11.2012
Сообщений: 1,525
20.08.2014, 14:33  [ТС]     Альтернативный вызов функции #60
Цитата Сообщение от DrOffset Посмотреть сообщение
говорили в первых сообщениях, решение ----- не опровергло
Меня не интересует опровержение, не интересует "тип типизации", и др. Меня интересует решение задачи.
Цитата Сообщение от DrOffset Посмотреть сообщение
подчиняется законам статической типизации, работает только на этапе компиляции и в динамике работать не будет.
Тоже не интересует то как в "тонком" плане всё это работает (имею ввиду "на каком этапе" и т.п., вы это красиво разсказываете, но это не более чем информация, которая никак не решает саму задачу).
Как раз таки то что явно я могу не приводить кол-во аргументов для вызова - уже решает 1/3 задачи. (осталось 1-решить проблему с возвращяемым значением и 2-как нибудь массив передать, чтоб явно не писать кол-во аргументов в me или call)
Цитата Сообщение от DrOffset Посмотреть сообщение
от чего-то это решением не считаешь
Не хочу использовать стороннюю библиотеку, по крайней мере пока я точно не буду уверен что ещё два пункта не могут быть решаемы стандартными С++ методами.
Цитата Сообщение от DrOffset Посмотреть сообщение
написать отдельный модуль на ассемблере
Не выход, уже обсуждалось.
Цитата Сообщение от DrOffset Посмотреть сообщение
для конкретного компилятора и конкретной платформы
Вот это эпик фэйл, представляю, программа работает на моём компе (win7 32бита). А на любом другом компе с теми же 32битами и win7 работать не будет - зачем такая программа тогда...
Цитата Сообщение от DrOffset Посмотреть сообщение
WinAPI ничего не знает ни про any, ни про type_info, т.к. написано на С
И не должен, WinApi это библиотека работа с окнами в среде windows) (поправлять не надо, я просто общую суть изложил)
Цитата Сообщение от DrOffset Посмотреть сообщение
И сами функции WinAPI не рассчитанны на динамическую типизацию
А какие то разсчитаны? Например функции из stdio.h?
Цитата Сообщение от DrOffset Посмотреть сообщение
Если бы она стоила такого решения, то это решение давно было бы у всех на виду и все бы им пользовались
Это далеко не всем надо, а я этим занимаюсь потому что мне нравится динамика и нравится программирование, ещё нравится Си. Но сидеть в статике я не хочу, потому и ищу выход из сложившейся ситуации.

Теперь код:
C++
1
 auto me = GetProcAddressProto(hMod, MessageBoxA);
Не вариант, я же сказал что у меня в txt виде названия функций, т.е. в программе их не будет. Предложенный вариант я так понимаю не сможет мне строку прочтённую из файла типа char* преобразовать в название функции так как это вы показали.

Ещё раз повторю, задача строится на том чтобы описать вызовы тысяч функций через одну процедуру (я понимаю что я не правильно выражаюсь, но абстрактно смысл должен быть понятен).

Добавлено через 2 минуты
DrOffset, ну серьёзно, ты же видиш что я хочу, зачем лишнее пишеш? Быт заел?

Цитата Сообщение от Jupiter Посмотреть сообщение
еще бисеру насыпьте
Очень смешно... ну прям упасть и не встать. ~ ~
Yandex
Объявления
20.08.2014, 14:33     Альтернативный вызов функции
Ответ Создать тему
Опции темы

Текущее время: 20:39. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru