передающий функтор как указатель функции

Если Вы надеетесь обнаруживать non-UTF кодировку (т.е. никакой BOM), Вы в основном до эвристики и статистического анализа текста. Вы могли бы хотеть смотреть на документ Mozilla об обнаружении универсального набора символов ( та же ссылка с лучшим форматированием с помощью Wayback Machine ).

41
задан dagw 3 December 2009 в 14:02
поделиться

9 ответов

Вы не можете напрямую передать указатель на объект функтора C ++ как указатель функции на код C (или даже в код C ++).

Кроме того, для переносимой передачи обратного вызова в код C он должен быть как минимум объявлен как extern «C» функция, не являющаяся членом. По крайней мере, потому что некоторые API требуют определенных соглашений о вызове функций и, следовательно, дополнительные модификаторы объявления.

Во многих средах C и C ++ имеют одинаковые соглашения о вызовах и отличаются только при изменении имени, поэтому любая глобальная функция или статический член будет работать. Но вам все равно нужно обернуть вызов operator () в обычную функцию.

  • Если ваш функтор не имеет состояния (это объект, просто чтобы удовлетворить некоторые формальные требования и т. д.):

     class MyFunctor {
     // нет состояния
     общественность:
     MyFunctor ();
     int оператор () (SomeType & param) const;
    }
    

    вы можете написать обычную функцию extern "C", которая создает функтор и выполняет его operator ().

     extern "C" int MyFunctorInC (SomeType * param)
    {
     статический MyFunctor my_functor;
     return my_functor (* параметр);
    }
    
  • Если у вашего функтора есть состояние, например:

     class MyFunctor {
     // Здесь несколько полей;
     общественность:
     MyFunctor (/ * некоторые параметры для установки состояния * /);
     int оператор () (SomeType & param) const;
     // + несколько методов для получения результата.
    }
    

    и функция обратного вызова C принимает какой-то параметр состояния пользователя (обычно void *):

     void MyAlgorithmInC (SomeType * arr,
     int (* весело) (SomeType *, void *),
     void * user_state);
    

    вы можете написать обычную внешнюю функцию «C», которая преобразует свой параметр состояния в ваш объект-функтор:

     extern "C" int MyFunctorInC (SomeType * param, void * user_state)
    {
     MyFunctor * my_functor = (MyFunctor *) user_state;
     return (* my_functor) (* параметр);
    }
    

    и используйте его так:

     MyFunctor my_functor (/ * параметры настройки * /);
    MyAlgorithmInC (input_data, MyFunctorInC, & my_functor);
    
  • В противном случае это единственный нормальный способ сделать это (нормально, как "без генерации машинного кода во время выполнения" и т. д.) заключается в использовании некоторого статического (глобального) или локального хранилища потока для передачи функтора к внешней функции "C". Это ограничивает то, что вы можете делать со своим кодом, и некрасиво, но будет работать.

53
ответ дан 27 November 2019 в 00:39
поделиться

Я нашел этот « драгоценный камень » с помощью Google. По-видимому, возможно, но я бы не рекомендовал это. Прямая ссылка на пример исходного кода.

7
ответ дан 27 November 2019 в 00:39
поделиться

Нет, конечно. Подпись вашей функции C принимает аргумент как функцию.

void f(void (*func)())
{
  func(); // Only void f1(), void F2(), ....
}

Все уловки с функторами используются шаблонными функциями:

template<class Func>
void f (Func func)
{
    func(); // Any functor
}
5
ответ дан 27 November 2019 в 00:39
поделиться

Функция обратного вызова AC, написанная на C ++, должна быть объявлена ​​как функция extern «C» , поэтому прямое использование функтора невозможно. Вам нужно будет написать какую-то функцию-оболочку для использования в качестве этого обратного вызова и заставить эту оболочку вызывать функтор. Конечно, протокол обратного вызова должен иметь некоторый способ передачи контекста функции, чтобы она могла добраться до функтора, иначе задача станет довольно сложной. У большинства схем обратного вызова есть способ передать контекст, но я работал с некоторыми бездумными, которые этого не делают.

См. Этот ответ для получения дополнительной информации (и посмотрите в комментариях неофициальные доказательства того, что обратный вызов должен быть extern «C» , а не только статическая функция-член):

3
ответ дан 27 November 2019 в 00:39
поделиться

Я не думаю, что вы можете: operator () в объекте функции действительно является функцией-членом, а C ничего не знает о них.

Вы должны уметь использовать бесплатные функции C ++ или статические функции классов.

2
ответ дан 27 November 2019 в 00:39
поделиться

Это зависит от того, статический ли это метод или метод экземпляра, если он статический, тогда вы можете передать функцию как className :: functionName, если это метод экземпляра, это будет более сложным, потому что вам, очевидно, нужно привязаться к определенному экземпляру, но вы не можете сделать это так же, как с делегатами в C # и т. д.

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

0
ответ дан 27 November 2019 в 00:39
поделиться

Я бы сказал нет, потому что функтор C ++ имеет перегруженный оператор () , который является функцией-членом , и, следовательно, для него потребуется указатель на функцию-член. Это совершенно другой тип данных, чем обычный указатель на функцию C, поскольку он не может быть вызван без экземпляра класса. Вам нужно будет передать обычную функцию или статическую функцию-член в библиотеку C. Поскольку перегруженный оператор () не может быть статическим, вы не можете этого сделать. Вам нужно будет передать C-библиотеку обычным образом,

0
ответ дан 27 November 2019 в 00:39
поделиться

Хм, может быть, вы могли бы написать бесплатную функцию-шаблон, которая обтекает ваши объекты-функции. Если все они имеют одинаковую подпись, это должно сработать. Примерно так (не проверено):

template<class T>
int function_wrapper(int a, int b) {
    T function_object_instance;

    return funcion_object_instance( a, b );
}

Это применимо для всех функций, которые принимают два целых числа и возвращают целое число.

0
ответ дан 27 November 2019 в 00:39
поделиться

Многие API-интерфейсы C, которые принимают обратные вызовы указателя функций, имеют параметр void * для состояния пользователя. Если у вас есть один из них, вам повезло - вы можете использовать функцию exterm C, которая обрабатывает данные пользователя как своего рода ссылку или ключ для поиска функтора, а затем выполняет его.

В противном случае - нет.

0
ответ дан 27 November 2019 в 00:39
поделиться