|
|
  |
передача указателя на функцию в функцию |
|
|
|
Nov 8 2007, 14:21
|
Местный
  
Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930

|
Цитата(Jurdens @ Nov 8 2007, 16:39)  Какие спец эффекты можно ожидать при преобразовании типов указателей на функцию В параметрах функции.
Например определим тип указатель на функцию с одним параметром типа указатель на неопределенный тип , функция ничего не возвращает typedef void (*CPU_FNCT_PTR)(void *); и тип указатель на функцию typedef void (*CPU_FNC)(char);
void func2(char ParF2 ); char Data; func1( void (* Fnc_par)(void *),void * ptrPar);
в параметре функции func1 передаем указатель на функцию с одним параметром типа указатель на неопределенный тип , функция ничего не возвращает.
Передадим указатель на функцию func2 как параметр func1 (приведя ее к типу CPU_FNCT_PTR) и передадим указатель на переменную Data как второй параметр приведя ее к типу void * ;. Получится такой вызов func1( (CPU_FNCT_PTR) func2, ( void *)Data);
…….
func1( void (* Fnc_par)(void *),void * ptrPar) { *Fnc_par( * ptrPar); // Сработает func2 ? или // надо преобразовать *((CPU_FNC ) Fnc_par) ( ( сhar*) ptrPar); };
А хотелось бы просто указатель на произвольную функцию и ее аргумент тип которого заранее неизвестен Ну а кто Вам мешает описать еще несколько функций описать так же как func2 и передавать их в func1? Ведь в описании func1 - у Вас нет ни слова про то, что ей годится только fun2 - не так ли? По-моему все сработает, если Вы вот так запишете: func1( (CPU_FNCT_PTR) function, ( void *)Data); ……. func1( (CPU_FNCT_PTR) function, ( void *)Data) { function(Data); }; Причем сработает для любой функции(func2, func3, func4 ...), если все они будут описаны так же как func2. Что передадите в func1 - то из нее и будет вызвано...
Сообщение отредактировал Николай Z - Nov 8 2007, 14:22
|
|
|
|
|
Nov 9 2007, 07:00
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Непомнящий Евгений @ Nov 9 2007, 09:21)  Когда вы вызываете функцию, компилятору надо знать типы передаваемых параметров и тип возвращаемого значения, чтобы расположить все это на стеке и в регистрах нужным образом. Если вызвать функцию void func(char t), используя указатель void (*P)(void*), то что из этого получится будет целиком зависеть от реализации компилятора. Например, если аргументы передаются в стеке и функция должна их выбрать сама, то будет плохо. Тут второй вопрос - а зачем вам это надо? Что значит - передать аргумент неизвестного типа? Максимум - это указатель void*... Но смешивать указатель и char, как в вашем примере - ИМХО, прямой путь поиметь кучу траблов. Поддерживаю. Можно, конечно, извратиться, но это будет коряво и непереносимо. Вы лучше изложите задачу, и я уверен, что кто-нибудь предложит более элегантное решение.
|
|
|
|
|
Nov 9 2007, 08:26
|
Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 9-07-05
Пользователь №: 6 656

|
Цитата(scifi @ Nov 9 2007, 10:00)  Поддерживаю. Можно, конечно, извратиться, но это будет коряво и непереносимо. Вы лучше изложите задачу, и я уверен, что кто-нибудь предложит более элегантное решение. А задача такая запускать произвольную функцию по таймеру через время Time. У запускаемой функции неизвестен тип параметра (так надо ) в общем случае и возвращаемый параметр для этого мы должны передать ее адрес в функцию. DelayStart(unsigned Time, *Func(?)); Подумал в С++ есть механизм передачи по ссылке F(&data1,&Func1) может тут как то поэксперементировать?
|
|
|
|
|
Nov 9 2007, 09:09
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Jurdens @ Nov 9 2007, 11:26)  А задача такая запускать произвольную функцию по таймеру через время Time. Произвольную функцию, но она д.б. известна когда: - на этапе компиляции - на этапе выполнения. Цитата(Jurdens @ Nov 9 2007, 11:26)  У запускаемой функции неизвестен тип параметра (так надо ) Т.е. на этапе выполнения параметр известен, так ? Цитата(Jurdens @ Nov 9 2007, 11:26)  У запускаемой функции неизвестен ... и возвращаемый параметр У запускаемой функции возвращаемый параметр известен всегда. Цитата(Jurdens @ Nov 9 2007, 11:26)  Подумал в С++ есть механизм передачи по ссылке F(&data1,&Func1) может тут как то поэксперементировать? В С и С++ есть передача параметра по значению (по умолчанию) и по ссылке. PS. Я не понимаю, Вы решаете конкретную задачу или теоретик на досуге ?
|
|
|
|
|
Nov 9 2007, 09:36
|
Местный
  
Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930

|
Цитата(Непомнящий Евгений @ Nov 9 2007, 09:21)  Когда вы вызываете функцию, компилятору надо знать типы передаваемых параметров и тип возвращаемого значения, чтобы расположить все это на стеке и в регистрах нужным образом. Если вызвать функцию void func(char t), используя указатель void (*P)(void*), то что из этого получится будет целиком зависеть от реализации компилятора. Например, если аргументы передаются в стеке и функция должна их выбрать сама, то будет плохо. Тут второй вопрос - а зачем вам это надо? Что значит - передать аргумент неизвестного типа? Максимум - это указатель void*... Но смешивать указатель и char, как в вашем примере - ИМХО, прямой путь поиметь кучу траблов. И не только от реализации компилятора будет зависеть результат... Но так же еще и от специфики архитектуры процессора тоже будет зависеть. Мне не хотелось тут просто этого касаться... Но я согласен с тем, что поставленная в топе задача - достаточно надуманная или выковырянная из левой ноздри. Таких гарантированных общих решений обычно не бывает. Нужно знать конкретику ибо решение таких вещей "в общем" - это будет практически попытка переноса идеи "виртуальной функции" в термины С, которая для С как бы не совсем естественна. Можно же еще захотеть решить задучу вызова любой функции с любым списком параметров тоже... И заставить потом объектный код во всем этом разбираться, но вот зачем такие навороты и чего ради - совершенно неясно. Неясна цель и неопределена расплата за такую универсальность. Гонка за чрезмерной универсальностью - это либо недопонимание задачи, либо некий фанатизм. А вот реальная задача - всегда гораздо понятнее... Цитата(Jurdens @ Nov 9 2007, 11:26)  А задача такая запускать произвольную функцию по таймеру через время Time. У запускаемой функции неизвестен тип параметра (так надо ) в общем случае и возвращаемый параметр для этого мы должны передать ее адрес в функцию. DelayStart(unsigned Time, *Func(?));
Подумал в С++ есть механизм передачи по ссылке F(&data1,&Func1) может тут как то поэксперементировать? Первый вопрос - а зачем надо неизвестный тип параметра? Я почти уверен, что практически всегда можно свести параметры всех вызываемых функций к одному типу... Ниже скажу как... Механизм передачи по ссылке - есть вообще практически в любом языке - это просто: в стек кладется не значение параметра, а его адрес. В С - естественно он тоже есть... В Вашем случае у всех вызываеммых функций вполне можно свести параметры просто к указателю на структуры, которые будут иметь разную струтуру, но передавать можно просто Pointer на них, а любая ваша функция знает с какой именно структурой она работает. Вот вам уже и тип параметра - всегда один и тот же - просто указатель void и никаких разнотипных параметров... Ну и получится, что если у funct1 - cтруктура эта массив char symb[10] - то пусть его функция funct1 и знает а для вызываеющей функции это просто указатель &symb, для функции funct2 - параметр некая струтура Struct - общего вида, но вызывающей функции передается опять же только адрес этой структуры &Struct и ничего более... Может и коряво изложил - но суть примерно такая... И нету уже никаких передач параметров разных типов для вызывающей функции... Другой вопрос - насколько это будет универсально, мобильно и т.д. и т.п.
Сообщение отредактировал Николай Z - Nov 9 2007, 09:44
|
|
|
|
|
Nov 9 2007, 10:27
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(Jurdens @ Nov 9 2007, 11:26)  А задача такая запускать произвольную функцию по таймеру через время Time. У запускаемой функции неизвестен тип параметра (так надо ) в общем случае и возвращаемый параметр для этого мы должны передать ее адрес в функцию. DelayStart(unsigned Time, *Func(?)); Тогда вопрос - там, откуда будет вызвана эта самая Func, необходимо ей что-то передать. И откуда это что-то возьмется? И куда ляжет результат выполнения Func? Т.е. мы приходим к чему-то типа: Код typedef void*(*unifunc)(void *) void DelayStart(unsigned Time, unifunc func, void *arg, void **res);
...
void *f1(void * arg) { TMyStruct *a = (TMyStruct *)arg; TMyStruct *res; .... return res; }
void main() { TMyStruct a, *b; DelayStart(100, f1, &a, &b); ... }
|
|
|
|
|
Nov 9 2007, 10:40
|
Частый гость
 
Группа: Свой
Сообщений: 107
Регистрация: 9-07-05
Пользователь №: 6 656

|
В С и С++ есть понятие указателя на неопределенный тип (*void) который можно преобразовать (типизировать) под любой тип данных. , понятие указателя на функцию. а зачем ? когда можно использовать 255 конструкций if else или 16 switch case в которые вложены еще 16 switch case Иногда при разработке пишут несколько человек и один ставит другому задачу вот моя такая написать функцию которая вызывает функциюа какую это определяется динамикой работы всего устройства в процессе его работы некий пользователь нажимает кнопочки и при этом надо выполнять одни функции изменяются показания датчиков ,которые опрашивает устройство, надо, выполнять другие у которых есть аргументы и еще и разные. Этим всем занимается другой человек. Просто лишний раз неохота его беспокоить и с другой стороны интересно сталкивались ли другие с подобными задачами. Можно конечно сказать примерно тоже что на этом форуме типа Цитата ты определись какие функции будешь вызывать на этапе компиляции и немороч мне голову. Но это не корректно потому что такие приемы применяют и они работают , например в при написании операционок. Обещали их прислать. Цитата У вас есть халатик с перламутровыми пуговицами? .... А за чем вам? Может вам и этот подойдет
|
|
|
|
|
Nov 9 2007, 11:10
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(Jurdens @ Nov 9 2007, 13:40)  ... задачу вот моя такая написать функцию которая вызывает функцию а какую это определяется динамикой работы всего устройства в процессе его работы Язык не имеет средств вызвать функцию с неизвестной на этапе компиляции сигнатурой. Имхо, проще всего в этой ситуации потребовать, чтобы все такие функции обладали заранее установленной сигнатурой. К примеру: int func(int m1, int m2, void *p) - что то типа того, как сделаны функции сообщений в winapi. Вдогонку: Цитата(Jurdens @ Nov 9 2007, 13:40)  В С и С++ есть понятие указателя на неопределенный тип (*void) который можно преобразовать (типизировать) под любой тип данных. не под "любой тип данных", а под "указатель любого типа"...
|
|
|
|
|
Nov 9 2007, 11:59
|
Местный
  
Группа: Участник*
Сообщений: 418
Регистрация: 20-08-07
Пользователь №: 29 930

|
Цитата(Jurdens @ Nov 9 2007, 13:40)  В С и С++ есть понятие указателя на неопределенный тип (*void) который можно преобразовать (типизировать) под любой тип данных. , понятие указателя на функцию. а зачем ? когда можно использовать 255 конструкций if else или 16 switch case в которые вложены еще 16 switch case Иногда при разработке пишут несколько человек и один ставит другому задачу вот моя такая написать функцию которая вызывает функцию а какую это определяется динамикой работы всего устройства в процессе его работы некий пользователь нажимает кнопочки и при этом надо выполнять одни функции изменяются показания датчиков ,которые опрашивает устройство, надо, выполнять другие у которых есть аргументы и еще и разные. Этим всем занимается другой человек. Просто лишний раз неохота его беспокоить и с другой стороны интересно сталкивались ли другие с подобными задачами. Можно конечно сказать примерно тоже что на этом форуме типа и немороч мне голову. Но это не корректно потому что такие приемы применяют и они работают , например в при написании операционок. Обещали их прислать. Ваша проблема в том, (вернее конторы сначала, а уже как следствие - Ваша) что у Вас никто не желает реально заняться архитектурой проекта. Вообще-то при разработке любого сложного проекта обычно принято - для улучшения его структуры разбивать его на части и оговаривать интерфейсы отдельных компонентов. Вот если бы такая проработка была сделана - то никакой проблемы с "неопределенными" типами параметров просто не существовало даже если вызываемых функций было бы даже не 256 а 1024 или 4096... Да и такой Case - размерностью 16x16 - врядли бы понадобился... Просто похоже что Ваш проект вообще делается без какой-либо предварительной проработки... И вообще непонятно - что значит "не беспокоить" коллегу или руководителя, если есть непонятки в архитектуре того, что вы делаете? Он у Вас что - небожитель или все-таки участник проекта? Нормальный подход к разработке таков, что в случае надобности не надо стесняться и Генерального Директора дернуть за известное место и не один раз - если это нужный и важный для предприятия проект...
|
|
|
|
|
Nov 13 2007, 14:25
|

Гуру
     
Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874

|
Цитата(Jurdens @ Nov 9 2007, 13:40)  Можно конечно сказать примерно тоже что на этом форуме типа и немороч мне голову. Но это не корректно потому что такие приемы применяют и они работают , например в при написании операционок. Обещали их прислать. Применяют. Работают. Просто для передачи указателя на функцию. Тип функции при этом передается отдельно и потом интерпретируется при вызове  . Только все это implementation defined. Ну сами задумайтесь: функция хочет каких-то аргументов на стеке - и кто их туда положит, если в точке вызова вообще не известно, какие функция хочет аргументы? Если нужно вызывать функцию по таймеру - нужно в C создать функцию одного типа, например, void (*FPTR)( void* );, и передавать функции регистрации для таймера этот указатель и один аргумент - в зависящую от функции структуру, в которую будут положеты параметры функции. В плюсах такое лучше сделать абстрактным классом с одной чисто виртуальной функцией типа void f(); который будет вызываться таймером, и потомки будут реализовывать эту функцию и хранить параметры.
--------------------
Пишите в личку.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|