Нестатический метод класса в качесте callback'а
От: XOOIOOX  
Дата: 26.04.18 15:36
Оценка:
Есть некая либа RtAudio: https://www.music.mcgill.ca/~gary/rtaudio/index.html
Ей требуется callback-функция: https://www.music.mcgill.ca/~gary/rtaudio/RtAudio_8h.html#a112c7b7e25a974977f6fc094cef1a31f

Не могу раздуплить, как без лишних приседаний передать ей в качестве таковой "обычный" нестатический метод класса. Это вообще возможно?
Re: Нестатический метод класса в качесте callback'а
От: DiZSl  
Дата: 26.04.18 15:47
Оценка:
Здравствуйте, XOOIOOX, Вы писали:

XOO>Есть некая либа RtAudio: https://www.music.mcgill.ca/~gary/rtaudio/index.html

XOO>Ей требуется callback-функция: https://www.music.mcgill.ca/~gary/rtaudio/RtAudio_8h.html#a112c7b7e25a974977f6fc094cef1a31f

XOO>Не могу раздуплить, как без лишних приседаний передать ей в качестве таковой "обычный" нестатический метод класса. Это вообще возможно?


Надо передаввать еще указатель на объект
Отредактировано 26.04.2018 15:49 DiZSl . Предыдущая версия .
Re: Нестатический метод класса в качесте callback'а
От: dead0k  
Дата: 26.04.18 15:48
Оценка: 3 (1) +1
Здравствуйте, XOOIOOX, Вы писали:

XOO>Не могу раздуплить, как без лишних приседаний передать ей в качестве таковой "обычный" нестатический метод класса. Это вообще возможно?


class MyFancyClientClass
{
public:
  int RegularNonstaticMemberMethod(/*callback args without userData*/);
}

static int instanceDispatcher (/*callback args without userData*/, void *userData)
{
   MyFancyClientClass * target = static_cast<MyFancyClientClass*>(userData);
   return target->RegularNonstaticMemberMethod(/*callback args*/);
}
...
...
MyFancyClientClass foo;
...
RtAudio().OpenStream(....., instanceDispatcher, &foo,...)


ps/
вот с ErrorCallback-ом все печально, да.
Отредактировано 26.04.2018 15:55 dead0k . Предыдущая версия . Еще …
Отредактировано 26.04.2018 15:49 dead0k . Предыдущая версия .
Отредактировано 26.04.2018 15:49 dead0k . Предыдущая версия .
Re[2]: Нестатический метод класса в качесте callback'а
От: XOOIOOX  
Дата: 26.04.18 16:27
Оценка:
Здравствуйте, dead0k, Вы писали:

Супер! Спасибо!

D>вот с ErrorCallback-ом все печально, да.


Как понимаю, это более общий случай, когда нет void* userData?

В принципе, черт бы с ним, пусть error в статике крутится.
Re: Нестатический метод класса в качесте callback'а
От: kov_serg Россия  
Дата: 26.04.18 20:38
Оценка: +1
Здравствуйте, XOOIOOX, Вы писали:

XOO>Есть некая либа RtAudio: https://www.music.mcgill.ca/~gary/rtaudio/index.html

XOO>Ей требуется callback-функция: https://www.music.mcgill.ca/~gary/rtaudio/RtAudio_8h.html#a112c7b7e25a974977f6fc094cef1a31f

XOO>Не могу раздуплить, как без лишних приседаний передать ей в качестве таковой "обычный" нестатический метод класса. Это вообще возможно?


  Если шашечки не важны и нужно что бы просто ехало, то можно так
// example.cpp
#include <stdio.h>
#include <string>
struct RtAudioError { typedef int Type; };
typedef void(* RtAudioErrorCallback)(RtAudioError::Type type, const std::string &errorText);

// Thunk.h

struct Thunk {
    enum { max=8 }; // достаточное число. выбирается под задачу
    struct Callback {
        typedef void (*cb_fn)(void* ctx,RtAudioError::Type type, const std::string &errorText);
        cb_fn cb; void *ctx;
        Callback(cb_fn cb=0,void *ctx=0) : cb(cb),ctx(ctx) {}
    };
    static int set(int i,Callback cb);
    static RtAudioErrorCallback get(int i);
};

// Thunk.cpp

static Thunk::Callback thunk[Thunk::max];

int Thunk::set(int i,Callback cb) {
    if (i>=0 && i<max) { thunk[i]=cb; return 0; }
    return 1;
}

#define THUNK(n) \
    case n: { struct L { \
        static void fn(RtAudioError::Type type, const std::string &errorText) { \
            thunk[n].cb(thunk[n].ctx,type,errorText); \
        } \
    }; return L::fn; }

RtAudioErrorCallback Thunk::get(int i) { switch(i) {
    THUNK(0)
    THUNK(1)
    THUNK(2)
    THUNK(3)
    THUNK(4)
    THUNK(5)
    THUNK(6)
    THUNK(7)
    // столько сколько нужно
} return 0; }

// usage.cpp

struct A {
    void fn(RtAudioError::Type type, const std::string &errorText) { printf("A::fn\n"); }
    static void _fn(void *ctx,RtAudioError::Type type, const std::string &errorText) { ((A*)ctx)->fn(type,errorText); }
};

struct B {
    void fn(RtAudioError::Type type, const std::string &errorText) { printf("B::fn\n"); }
    static void _fn(void *ctx,RtAudioError::Type type, const std::string &errorText) { ((B*)ctx)->fn(type,errorText); }
};

void call(RtAudioErrorCallback cb) {
    std::string msg;
    cb(0,msg);
}

int main(int argc,char** argv) {
    A a[1]; B b[1];

    Thunk::set(0,Thunk::Callback(A::_fn,a));
    Thunk::set(1,Thunk::Callback(B::_fn,b));

    call(Thunk::get(0));
    call(Thunk::get(1));    
    return 0;
}
Re: Нестатический метод класса в качесте callback'а
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.04.18 21:35
Оценка: +1
Здравствуйте, XOOIOOX, Вы писали:

XOO>Есть некая либа RtAudio: https://www.music.mcgill.ca/~gary/rtaudio/index.html

XOO>Ей требуется callback-функция: https://www.music.mcgill.ca/~gary/rtaudio/RtAudio_8h.html#a112c7b7e25a974977f6fc094cef1a31f

XOO>Не могу раздуплить, как без лишних приседаний передать ей в качестве таковой "обычный" нестатический метод класса. Это вообще возможно?


Ну так там есть параметр
typedef int(* RtAudioCallback)(void *outputBuffer, void *inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void *userData)


При установке колбэка там наверняка передается *userData, которая потом в колбэк передается.

Вот туда и передавай указатель на this, а в качестве колбэка используй статическую функцию класса. В этой функции кастишь void к указателю на свой класс, и вызываешь уже нестатический метод. Этот прием стар, как само программирование.
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.