C ++ Functor как аргумент внешней функции fortran [duplicate]

Это позаботится о добавлении элемента в пустой DataFrame. Проблема в том, что df.index.max () == nan для первого индекса:

df = pd.DataFrame(columns=['timeMS', 'accelX', 'accelY', 'accelZ', 'gyroX', 'gyroY', 'gyroZ'])

df.loc[0 if math.isnan(df.index.max()) else df.index.max() + 1] = [x for x in range(7)]
36
задан dagw 3 December 2009 в 15:02
поделиться

10 ответов

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

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

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

  • Если ваш функтор не имеет состояния (это объект, который должен удовлетворять некоторым формальным требованиям и т. Д.):
    class MyFunctor {
      // no state
     public:
      MyFunctor();
      int operator()(SomeType &param) const;
    }
    
    вы можете написать нормальную внешнюю функцию «C», которая создает функтор и выполняет свой оператор ().
    extern "C" int MyFunctorInC(SomeType *param)
    {
      static MyFunctor my_functor;
      return my_functor(*param);
    }
    
  • Если ваш функтор имеет состояние, например:
    class MyFunctor {
      // Some fields here;
     public:
      MyFunctor(/* some parameters to set state */);
      int operator()(SomeType &param) const;
      // + some methods to retrieve result.
    }
    
    , а функция обратного вызова C принимает какой-то параметр состояния пользователя (обычно void *):
    void MyAlgorithmInC(SomeType *arr,
                        int (*fun)(SomeType *, void *),
                        void *user_state);
    
    вы можете написать обычный экстент «C ", которая передает свой параметр состояния объекту-функтору:
    extern "C" int MyFunctorInC(SomeType *param, void *user_state)
    {
      MyFunctor *my_functor = (MyFunctor *)user_state;
      return (*my_functor)(*param);
    }
    
    и использует его следующим образом:
    MyFunctor my_functor(/* setup parameters */);
    MyAlgorithmInC(input_data, MyFunctorInC, &my_functor);
    
  • В противном случае это единственный нормальный способ сделать это (нормальный как в" без генерации машинного кода во время выполнения »и т. д.) заключается в использовании некоторого статического (глобального) или потокового локального хранилища для передачи функтора на внешнюю функцию« С ». Это ограничивает то, что вы можете сделать с вашим кодом и является уродливым, но будет работать.
50
ответ дан Tomek Szpakowicz 26 August 2018 в 21:05
поделиться
  • 1
    +1, подробное описание возможных случаев. – Pavel Minaev 3 December 2009 в 18:55
  • 2
    +1, хотя подпись обратного вызова определенно не C :) – quinmars 3 December 2009 в 23:23
  • 3
    oops, nvm, каким-то образом я смешивал объявления и думал, что вы используете ссылки в C здесь. – quinmars 4 December 2009 в 00:24
  • 4
    @quinmars: Мне было интересно, как скоро кто-то запутался в этом. Вы должны любить ссылки на C ++ ... – Tomek Szpakowicz 4 December 2009 в 09:20
  • 5
    Хорошая рецензия. Будет ли это работать, если функция бесплатной обертки была функцией шаблона, как я описал в своем ответе ниже? – Björn Pollex 4 December 2009 в 11:31

Я нашел этот «g0] gem » с помощью google. Видимо, возможно, но я бы не рекомендовал его. Прямая ссылка в пример исходного кода.

7
ответ дан Andreas Brinck 26 August 2018 в 21:05
поделиться
  • 1
    Пожалуйста, не используйте это. Это должно быть тривиально обернуть ваш функтор в обычной функции C и не требует уродливого взлома. – Ron Warholic 3 December 2009 в 19:03
  • 2
    yuck, это действительно «черная магия». как название категории, в которой оно было подано, предлагает – 0xC0000022L 23 June 2011 в 18:57
  • 3
    Чистый камень Я думаю, что это только путь, потому что c вызывающий не знает, как нажать дополнительный параметр. Функция создается в ram, которая имеет этот «const». вызывающий абонент. – Luka Rahne 10 April 2013 в 20:38
  • 4
    Ошибка выполнения на ideone.com – lorro 21 June 2016 в 16:32

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

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

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

template<class Func>
void f (Func func)
{
    func(); // Any functor
}
3
ответ дан Benjamin 26 August 2018 в 21:05
поделиться

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

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

    return funcion_object_instance( a, b );
}

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

0
ответ дан Björn Pollex 26 August 2018 в 21:05
поделиться

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

0
ответ дан Charles Salvia 26 August 2018 в 21:05
поделиться

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

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

3
ответ дан Community 26 August 2018 в 21:05
поделиться

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

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

0
ответ дан Joe Gauterin 26 August 2018 в 21:05
поделиться

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

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

0
ответ дан Tim Ebenezer 26 August 2018 в 21:05
поделиться

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

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

2
ответ дан UncleBens 26 August 2018 в 21:05
поделиться

GCC позволяет конвертировать указатели на функции функций в простые указатели функций (первый аргумент функции, называемый указателем простой функции, затем this).

Проверьте соответствующую ссылку в руководстве .

Для этого требуется флаг -Wno-pmf-conversions, чтобы отключить соответствующее предупреждение для явно нестандартной функции. Очень удобно для взаимодействия библиотек стилей C с программированием на языке C ++. Когда указатель на функцию-член является константой, это даже не нужно генерировать код вообще: API будет использовать этот аргумент в любом случае.

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

Но по крайней мере, когда вы не проходите через функторы, это полезно и обеспечивает замену ссылки на C для std::mem_fn с <functional>.

1
ответ дан user3996901 26 August 2018 в 21:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: