Как использовать указатель на функцию пользовательского типа в C

#c #function-pointers

#c #указатели на функции

Вопрос:

Условие

Я использую фреймворк, который имеет пользовательский тип, как показано ниже:

 typedef log (*CustomType) (
  int timeStamp,
  const char* data,
  int dataSize,
  void* userData,
  int dataType,
  int viewId
)
  

и метод инициализации MyClass, как показано ниже:

 MyClass_Init (void **output, CustomType video, CustomType audio, void* userData)
  

Вопрос

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

 CustomType videoInput;
CustomType audioInput;
void *output  = malloc(sizeof(void*);
void *userData = malloc(sizeof(void*));                     
long result = MyClass_Init(amp;output, videoInput, audioInput, userData);
  

Комментарии:

1. Каков ваш вывод ошибки?

Ответ №1:

В этом коде есть несколько ошибок:

  1. Вы не можете смешивать указатели на функции и указатели на методы. Это сводится к тому, что метод this for a должен быть включен в сигнатуру вызова метода. Поскольку указатель на функцию не включает this указатель (это функция, а не указатель на метод), они не могут совпадать.

    Большинство API на основе C включает в себя какое-то ссылочное значение (большинство фреймворков вызывают эти refCon, context или userData), поэтому вы можете создать функцию адаптера, которая вызывает ваш метод. userData Параметр в вашем списке параметров CustomType выглядит так, как будто он один из них (обязательно обратитесь к документам).

    Вероятно, вы можете предоставить userData везде, где вы устанавливаете MyClass_Init в качестве обратного вызова. Итак, если была вызвана эта функция для обеспечения обратного вызова библиотеки set_callback( MyCustomType callback, void* userData ) , сделайте что-то вроде

       MyClass *obj = new MyClass; // Or however you create your object
      set_callback( MyClassCallbackAdapterFunction, obj );
      

    с помощью функции адаптера, например:

       log MyClassCallbackAdapterFunction( int timeStamp, const char* data, int dataSize, void* userData, int dataType, int viewId )
      {
          MyClass *myThis = (MyClass*) userData;
    
          // Here you can now call myThis->MyClass_Init( ... ) however you want to.
      }
      
  2. malloc( sizeof(void*) ) Заявления выглядят так, как будто вы неправильно понимаете возвращаемые параметры (некоторые преподаватели также называют их «побочными эффектами»). У меня нет документов для любого используемого вами API / библиотеки, но я почти уверен, что вы должны не просто передавать буферы размером с указатель. Либо вы просто указываете указатель на стек, в который будет возвращен буфер, либо предоставляете весь буфер (например, массив) и его размер, и именно туда обратный вызов будет записывать или около того.