2012-06-20 3 views
1

Я пытаюсь создать карту имен функций и указателей функций с помощью __stdcall. Вот как я в настоящее время получить свои указатели на функции:Создание карты __stdcall

typedef int (CALLBACK* InitializeDLL)(int,int); 
InitializeDLL initializeDLL = (InitializeDLL)GetProcAddress(hInstanceLibrary, "InitializeDLL"); 

и теперь моя карта:

map<string, int *__stdcall> mapInt; 
mapInt["InitializeDLL"] = initializeDLL; //throws error for "InitializeDLL cannot be assigned to entity of type int*" 

Эта ошибка является именно то, что я ожидал, но мне нужно добавить тип, видимо, перед __stdcall. Если удалить «ИНТ» в передней части, то она жалуется:

Error: expected a type specifier 

Если я пытаюсь скомпилировать его только после создания объекта карты с «Int», включенным в передней, он выдает ошибку:

error C2059: syntax error : '>' 

Это не имеет для меня никакого смысла. Итак, каков правильный способ использования __stdcall как типа для карты? Добавление int перед ним показалось мне подозрительным, но если я его не добавлю, он жалуется, что ему нужен указанный тип.

Кроме того, CALLBACK является #define для __stdcall, если это сбивает с толку.

+0

http://stackoverflow.com/questions/8304582/how-to-store-functional-objects-with-difrent-signature-in-a-container-eg-std#8304694 –

+1

'__stdcall' больше не является тип, чем 'const'. Они просто модификаторы типа. –

ответ

3

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

Возможно CallbackFunction будет лучшим названием для этого ЬурейеГо, так как она включает в себя все функции, имеющими подписи, который может использоваться для обратного вызова:

typedef int (CALLBACK* CallbackFunction)(int,int); 
CallbackFunction initializeDLL = 
    (InitializeDLL)GetProcAddress(hInstanceLibrary, "InitializeDLL"); 
map<string, CallbackFunction> mapInt; 
mapInt["InitializeDLL"] = initializeDLL; 

Есть более общие способы управления функциями (и даже функции-члены). Если вы способны/хотите использовать новые возможности C++ 11, вы можете использовать std::function и std::bind. Если нет, то вы можете использовать boost::function и boost::bind. Версия Boost и C++ 11 этих объектов используется точно так же. Документация Boost будет намного полезнее, чем cppreference.

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


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

Вы также можете рассмотреть возможность передачи списка параметров в функции обратного вызова в виде std::vector<boost::any> или std::vector<boost::variant>. Функция обратного вызова затем преобразует каждый boost::any или boost::variant в конкретный тип, связанный с этим конкретным параметром. Если типы параметров команды имеют простые встроенные типы, вы можете даже использовать std:vector<UnionOfPossibleParameterTypes>, где UnionOfPossibleParameterTypes - простой старый C-стиль union.

+0

Это больше похоже на то, о чем я думал, но у меня все еще будет много вариаций CallbackFunction для разных типов возвращаемых данных и конфигураций параметров. Нет никакого общего способа указать на любой CALLBACK * typedef, который я делаю? –

+0

@Atlos: См. Обновленный ответ. –

+0

В интересах времени я пошел с копированием вручную, сравнивая каждую строку имени функции со списком известных функций и затем выбрав соответствующую команду. Я дам более «изящный» способ выстрела в другое время. –

4

Вы используете __stdcall как тип, но он не один. Вы должны использовать свой тип указателя функции в определении карты.

map<string, InitializeDLL> mapInt; 

Я не знаю, почему вы пытались сделать что-то еще, в первую очередь, так как вы уже использовали этот тип в другом месте, не будет ли это было очевидно, что это было необходимо здесь, а?

+0

Хорошо, что было бы бессмысленно иметь карту с InitializeDLL, потому что тогда мне нужно было бы создать карту для каждой функции и победить цель использования карт в первую очередь. Я думал, что __stdcall был каким-то образом получить указатель на функцию, но, как объяснялось мне в чате, это ничем не отличается от попытки передать что-то вроде «const» как тип. –

+2

@Atlos: Даже если вы можете использовать '__stdcall' как тип, как он приближает вас к' void *'? Вам по-прежнему требуется гораздо больше информации, чтобы фактически использовать указатель. – tenfour