Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564

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

15.08.2014, 10:44. Показов 6827. Ответов 66
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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] аргумент думаю будет идти как возвращяемое значение функции)... (может как то можно использовать в данном случае переменное кол-во аргументов в функции?)
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.08.2014, 10:44
Ответы с готовыми решениями:

Вызов функции внутри другой функции с передачей локальной переменной по ссылке
Столкнулся с очень с интересной проблемой. Можно ли так делать? #include &lt;iostream&gt; using std::cout; void f(const int...

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

Вызов родовой функции (нужно передать массив в качестве аргумента функции через указатель)
#include &lt;iostream&gt; using namespace std; template &lt;class T1&gt; class mas { public: T1 n; T1 a; void input() ...

66
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
19.08.2014, 08:17  [ТС]
Студворк — интернет-сервис помощи студентам
Что то пример который дал 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-r... 39779.aspx
но почему же компиляционные ошибки то(

Добавлено через 9 минут
При этом MSDN пишет:
В C++ оператор ... используется в блоках обработки исключений catch, а в C++11 — для шаблонов с переменным числом аргументов.
Типа только в 2011+ версиях будет работать?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
19.08.2014, 09:10
Цитата Сообщение от Izual Посмотреть сообщение
Типа только в 2011+ версиях будет работать?
Ага, начиная с VS 2013 или VS 2012 с последним обновлением. Как я уже говорил, это С++11 (действующий стандарт С++), а в VS достаточно инертно добавляют его поддержку (таблица поддержки возможностей на MSDN), в GCC и Clang давно все реализовано.
Кстати на С стандарт тоже обновился и тоже в 2011 году.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
19.08.2014, 10:33  [ТС]
Да заработало (установил 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;
...
}
}
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
19.08.2014, 15:17
Izual,
Цитата Сообщение от Izual Посмотреть сообщение
и в соответствии с типом сделать (что конешно вот меня не радует прототипы вызова для всех возможных возвращяемых значений...
Только так скорее всего. Ведь для того, чтобы вызвать функцию нам нужно знать ее тип и если аргументы еще можно вывести неявно, то возвращаемый тип без сигнатуры не узнать.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
19.08.2014, 15:27  [ТС]
Цитата Сообщение от 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 это сделано, хотя я думаю что это не подойдёт, ну может как то по другому можно..
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
19.08.2014, 16:05
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 к нужному типу.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
19.08.2014, 16:49  [ТС]
Не знаю в тему ли, но накапал: http://www.drdobbs.com/cpp/ext... 586?pgno=2

Используется Variant... может и в возвращяемое значение его получится сунуть в моём случае?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
19.08.2014, 17:39
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.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
19.08.2014, 22:19
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.
1
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.08.2014, 07:42  [ТС]
Цитата Сообщение от 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/refer... info/name/)
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
20.08.2014, 08:33
Цитата Сообщение от 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 которые планируются использовать - должны оперировать те ме же категориями, тогда все модули друг друга поймут. Общего же решения забесплатно не будет.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
20.08.2014, 09:03
Так я же не могу динамически изменять "<int>" в соответствии с типом, т.е. мне придётся в ручную прописывать опять же все эти типы вызовов функций.
Кодогенерация? Пишешь скрипт на Python/Perl который бегает по заголовочным файлам и делает обетрку над функциями.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.08.2014, 09:41  [ТС]
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
скрипт на Python/Perl
Это не вариант... по крайней мере для меня. Я думаю что решение есть, на С++, только те кто знают не говорят)
Цитата Сообщение от DrOffset Посмотреть сообщение
во всей системе централизовано
надо найти центр)))
Что то последние посты меня не вдохновляют, пойду пить йад.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
20.08.2014, 09:58
Izual, Не вдохновляют потому что вы пытаетесь решить проблему на языке не предназначенном для решения этой проблемы. Гвозди тоже можно топором забивать, но зачем, если есть молоток?
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.08.2014, 10:48  [ТС]
ForEveR, слушайте, мне по поводу первого вопроса тоже говорили тоже самое. Но пришёл StailGot и показал как решить проблему. Не полностью, но это видимо потому что за 3 страницы опять наспамили (ну как обычно пока истину найдёш, куча подводных вопросов и ответов вышло).
Так что я думаю что и из оставшейся задачи тоже есть решение. Я не просто "думаю", я верю, потому что если бы С++ не мог бы решить подобные проблемы, то наверно уже давно бы другие языки были более популярны, а Си бы умер.
Цитата Сообщение от ForEveR Посмотреть сообщение
можно топором забивать
Ответ в многофункциональности, есть и мульти-инструмент, где с одной стороны топорище, а с другой "молотище"
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
20.08.2014, 10:58
Izual, С++ используется для решения своих задач. С++ статически-типизированный язык. Проблема использованием variadic-templates не решилась, мы все равно остались в границах этапа компиляции, а не этапа выполнения.
Послушайте DrOffset или Dmitriy_M, либо действительно полностью динамическое окружение (как в интерпретируемых, а не комилируемых языках или же как в языках с виртуальной машиной), либо кодогенерация.
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.08.2014, 12:07  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
остались в границах этапа компиляции, а не этапа выполнения
Меня это мало волнует. Меня интересует лишь возможность решения моей задачи, способы решения и подводные камни.

Добавлено через 14 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
Послушайте DrOffset или Dmitriy_M
Я слушаю что говорят, многое что было сказано было полезным, хотя бы для ознакомления, так сказать опыт. Но решая задачу, так сказать, и метод реализации очень важен. Победу можно одержать разными путями, и пренебрегать какими то, может и не понятными для других, моментами я не хочу. Я уже вышел за рамки того что я хотел использовать приближенные к старому Си методы, ввиду того что просто невозможно было выполнить искомое, однако изучать ещё 100500 языков не вижу смысла, лучше в этом буду капаться дальше, и возможно решение найдётся.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
20.08.2014, 13: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 реальный прототип).
2
20.08.2014, 14:29

Не по теме:

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

0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.08.2014, 14:33  [ТС]
Цитата Сообщение от 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 Посмотреть сообщение
еще бисеру насыпьте
Очень смешно... ну прям упасть и не встать. ~ ~
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.08.2014, 14:33

Вызов функции визуал бейсика из функции явы скрипта
Как такое соорудить, есть например две наипростецкие функции: &lt;% function base() h11='123' base = h11 end function %&gt; ...

Вызов функции из другой функции после нажатия на кнопку
Помогите, пожалуйста! Никак не могу понять почему не запускается функция d() Полный код: &lt;script language=&quot;javascript&quot;&gt;...

Вызов массива, сформированной в одной функции с другой функции
Здравствуйте! Есть разрабатываемое решение - состоящее из main.cpp и array.cpp Main - выражает собой меню в консольном режиме по...

Автоматический вызов функции при вызове функции
Доброго времени суток! Есть задача по событие вызова некой функции назовем ее function1(), автоматически должна срабатывать функция...

Не работает без указателя вызов функции в функции
int AmountOfSquares(int **Array) { NumberOfSquares++; for (i = iTempTwo + 1; ((i&lt;(iTemp + SizeOfSquare)) &amp;&amp;...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Сезонность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru