Как передать функцию в pthreads из C ++? [Дубликат]

Вы можете использовать метод JavaScript sort с функцией обратного вызова:

function compareASC(homeA, homeB)
{
    return parseFloat(homeA.price) - parseFloat(homeB.price);
}

function compareDESC(homeA, homeB)
{
    return parseFloat(homeB.price) - parseFloat(homeA.price);
}

// Sort ASC
homes.sort(compareASC);

// Sort DESC
homes.sort(compareDESC);
14
задан Johannes Schaub - litb 8 April 2011 в 04:51
поделиться

3 ответа

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


Что касается второго вопроса : Да, это работает, но typedef не находится внутри шаблона. Я попытался поместить такой тип typedef внутри класса, но оказывается, что даже шаблоны классов не допускаются внутри extern "C". Таким образом, у вас может быть шаблон функции, но нет параметров зависимого типа.

Простое определение этой функции легко:

extern "C" typedef void ftype(int);

template<typename T>
static ftype f; // <- added "static" here

template< typename T >
void f(int q) {}

Aha, вариативные функции!

extern "C" typedef void ftype( int, ... );

template<typename T>
static ftype f;

template< typename T >
static void f( int z, ... ) {
    va_list va;
    va_start( va, z );
    T v = va_arg( va, T );
    va_end( va );

    std::cout << v;
}

Вам действительно не нужно выводить тип, поскольку это всего лишь обратный вызов, поэтому вы можете передать это & f<int> в код C, все обратные вызовы имеют один и тот же тип, и он может сделать определение типа во время выполнения и передать все он хочет через varargs.

3
ответ дан Potatoswatter 22 August 2018 в 01:52
поделиться
  • 1
    Я использовал extern "C" { ... } вместо extern "C" ..., потому что последнее не позволяет объединить его с static в одном объявлении. – Johannes Schaub - litb 8 April 2011 в 04:28
  • 2
    @Johannes: Но вы сказали «Итак, чтобы не допустить отключение мангала ...», чего я не понимаю. Mangling все еще отключен, поэтому компилятор должен жаловаться. – Potatoswatter 8 April 2011 в 04:31
  • 3
    @Potatoswatter этот параграф применяется, если второе объявление объявляет ту же функцию, что и первая. Я думал, что, поскольку эти два типа отличаются друг от друга («Два типа функций с разными языковыми связями - это разные типы, даже если они в ином случае идентичны»), а две объявления функций, использующие разные типы, перегружают друг друга («По расширению, два объявления в той же области действия, которые объявляют одно и то же имя, но с разными типами, называются перегруженными объявлениями "), что они объявляют разные функции. – Johannes Schaub - litb 8 April 2011 в 05:52
  • 4
    @Johannes: Эта часть довольно непонятна, так как шаблонам запрещается иметь C-языковую связь вообще (14/4). Таким образом, static ftype f может быть несоответствующим. Но в начале этого параграфа упоминаются имена, и в основном обсуждается видимость, поэтому он не может ссылаться на тип функции. – Potatoswatter 8 April 2011 в 06:11
  • 5
    @Johannes: Ну ... мой 2 ¢ заключается в том, что эту проблему лучше решить, отделив шаблоны от C с помощью механизма отправки или используя макросы в качестве шаблонов. Особенно, если это касается клиента / работодателя. – Potatoswatter 8 April 2011 в 06:20

... есть ли легкая работа для достижения моей первоначальной цели?

вы можете приблизиться к ней с нескольких углов, в зависимости от того, как вы хотите настроить и объявить их.

четыре подхода, одно пространство имен демонстрирует каждый. «Тип», пожалуй, самый простой для вашего использования.

#include <stdio.h> // favored to reduce exports in later demonstration

#define FUNC_NAME __PRETTY_FUNCTION__
// or __func__ or __FUNCTION__ or...

extern "C" {

    /* C prototype */
    typedef void ftype(int a);

    /* the c function all our functions are piped into */
    void call(ftype* a);

    /* helper which serves as the implementation for our functions */
    void print(int a, const char* const func);

    /* C definitions (used in namespace examples below) */
    static void static_float(int a) {
        print(a, FUNC_NAME);
    }

    static void static_double(int a) {
        print(a, FUNC_NAME);
    }

    void extern_float(int a);
    void extern_float(int a) {
        print(a, FUNC_NAME);
    }

    void extern_double(int a);
    void extern_double(int a) {
        print(a, FUNC_NAME);
    }

    static void static_function_float(int a) {
        print(a, FUNC_NAME);
    }

    static void static_function_double(int a) {
        print(a, FUNC_NAME);
    }

} /* << extern C */

namespace Extern {

    /**
     interface demonstrates C functions as template arguments
    */
    template<ftype Fn>
    struct t_func {
        static ftype* Function() {
            return Fn;
        }
    };

    template<typename T> struct bind;

    template<> struct bind<float> {
        typedef t_func<extern_float> F;
    };

    template<> struct bind<double> {
        typedef t_func<extern_double> F;
    };

    template<typename T>
    void Call(T a) {
        (void) a;
        call(bind<T>::F::Function());
    }

} /* << Extern */

namespace Static {

    /**
     interface demonstrates template types wrapping static C functions
     */
    template<typename T> struct bind;

    template<> struct bind<float> {
        static ftype* F() {
            return static_float;
        }
    };

    template<> struct bind<double> {
        static ftype* F() {
            return static_double;
        }

    };

    template<typename T>
    void Call(T a) {
        (void) a;
        call(bind<T>::F());
    }

} /* << Static */

namespace Function {

    /**
     interface demonstrates template functions wrapping static C functions
     */

    template<typename T> ftype* bind();

    template<> ftype* bind<float> () {
        return static_function_float;
    }

    template<> ftype* bind<double> () {
        return static_function_double;
    }

    template<typename T>
    void Call(T a) {
        (void) a;
        call(bind<T> ());
    }

} /* << Function */

namespace Type {

    /**
     interface demonstrates template types implementing static functions.
     although gcc4.2 and clang both compile it, i'm uncertain that this is conforming.
    */

    template<typename T> struct bind {
        static void F(int a);
    };

    template<> void bind<float>::F(int a) {
        print(a, FUNC_NAME);
    }

    template<> void bind<double>::F(int a) {
        print(a, FUNC_NAME);
    }

    template<typename T>
    void Call(T a) {
        (void) a;
        call(bind<T>::F);
    }

} /* << Type */

int main(int argc, const char * argv[]) {
    (void) argc;
    (void) argv;

    const float f(1.0f);
    const double d(5.0);

    Extern::Call(f);
    Extern::Call(d);

    Static::Call(f);
    Static::Call(d);

    Function::Call(f);
    Function::Call(d);

    Type::Call(f);
    Type::Call(d);

    return 0;
}

void call(ftype* a) {
    a(11);
}

void print(int a, const char* const func) {
    printf("%i: %s\n", a, func);
}

выходы:

11: void extern_float(int)
11: void extern_double(int)
11: void static_float(int)
11: void static_double(int)
11: void static_function_float(int)
11: void static_function_double(int)
11: static void Type::bind<T>::F(int) [with T = float]
11: static void Type::bind<T>::F(int) [with T = double]

:

nm unstripped:
    0000000100000daf s  stub helpers
    0000000100001048 D _NXArgc
    0000000100001050 D _NXArgv
    0000000100000bde T __ZN4Type4bindIdE1FEi
    0000000100000bc0 T __ZN4Type4bindIfE1FEi
    0000000100000d98 s __ZZ12extern_floatE19__PRETTY_FUNCTION__
    0000000100000c98 s __ZZ12static_floatE19__PRETTY_FUNCTION__
    0000000100000d80 s __ZZ13extern_doubleE19__PRETTY_FUNCTION__
    0000000100000cb0 s __ZZ13static_doubleE19__PRETTY_FUNCTION__
    0000000100000d60 s __ZZ21static_function_floatE19__PRETTY_FUNCTION__
    0000000100000d38 s __ZZ22static_function_doubleE19__PRETTY_FUNCTION__
    0000000100000cc8 s __ZZN4Type4bindIdE1FEiE19__PRETTY_FUNCTION__
    0000000100000d00 s __ZZN4Type4bindIfE1FEiE19__PRETTY_FUNCTION__
    0000000100001060 D ___progname
    0000000100000000 A __mh_execute_header
    0000000100001058 D _environ
                     U _exit
    0000000100000c00 T _extern_double
    0000000100000b20 T _extern_float
    0000000100000c20 T _main
                     U _printf
    0000000100000b60 t _static_double
    0000000100000b40 t _static_float
    0000000100000ba0 t _static_function_double
    0000000100000b80 t _static_function_float
                     U dyld_stub_binder
    0000000100000ae0 T start


nm stripped:
    0000000100000000 A __mh_execute_header
                     U _exit
                     U _printf
                     U dyld_stub_binder

извините, я не позаботясь о стандартах сегодня - надеюсь, что это поможет. удачи!

1
ответ дан justin 22 August 2018 в 01:52
поделиться

Я не знаю причину ограничения, но не можете ли вы использовать функцию обёртки extern "C", которая вызывает конкретный экземпляр шаблона, о котором вы заботитесь?

1
ответ дан Mark B 22 August 2018 в 01:52
поделиться
Другие вопросы по тегам:

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