Здравствуйте, beyv, Вы писали:
B>Основная загвоздка у ТС получения доступа к полям класса в теле колбека или где там.
нет, у него классическая проблема — имеющийся код принимает указатель на сишную функцию и вызывает её именно как сишную функцию. если ты вместо этого передашь адрес класса, то естественно ничего не выйдет
и пож-та не хами, даже если ты полностью уверен в своей правоте
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>[/q] EP>Эта библиотека принимает только указатель на функцию, и не позволяет прямым способом передать контекст — чем тут поможет этот FastDelegate?
Здравствуйте, beyv, Вы писали:
EP>>Эта библиотека принимает только указатель на функцию, и не позволяет прямым способом передать контекст — чем тут поможет этот FastDelegate? B>В с(++) есть скобочки: B>
Здравствуйте, AHOHUM, Вы писали:
AHO>Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
есть пример как можно автоматически сохранить функциональный объект (лямбду/результат bind) в глобальный нумерованный объект и получить указатель на функцию. Например:
internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
Хотелось бы в плюсах 11, чтобы сallback вызывал метод класса. Решение со статическим методом и глобальным this – совсем уж убого.
Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
addCallback(state, [] (void * internalState, Data * data) {});
естественно не имею доступа к полям класса в теле,
addCallback(state, [this]/[&] (void * internalState, Data * data) {});
или
void Class::method(void * internalState, Data * data);
addCallback(state, std::bind(&Class::method, this, std::placeholders::_1, std::placeholders::_2));
Здравствуйте, AHOHUM, Вы писали:
AHO>В чём загвоздка?
В том что лямбда и бинд создают функциональные объекты. И использовать их может только код, который умеет работать с функциональными объектами. Так что ни как.
Что касается С колбек, то скорее всего в internalState есть место где хранить указатель на класс, вы его просто не нашли.
Здравствуйте, AHOHUM, Вы писали:
AHO>Имеется С библиотека с неизменяемым интерфейсом
AHO>В чём загвоздка?
std::bind возвращает совсем не Callback *, так что, если интерфейс библиотеки совсем не предполагает хранения указателей на некоторые пользовательские данные, то это придется делать самому. Например, можно держать в статическом поле класса ::std::map< /* internalState */ void *, Class * > и при вызове коллбэка находить соответствующий экземпляр класса.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, AHOHUM, Вы писали:
AHO>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так: AHO>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
обычно в C библиотеках дают возможность просунуть void* userData, поищите внимательнее, либо сообщите название библиотеки, чтобы мы убедились
AHO>Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
по задумке нельзя. лямбды можно скастить к указателю на функцию только если она не захватывает никаких переменных в контекст
AHO>В чём загвоздка?
на самом деле ваша проблема довольно распространена и существует несколько подходов для ее решения
1) заводим глобальную переменную, кладем туда this, пишем глобальную функцию, которая имеет сигнатуру Callback и которая при вызове сделает перевызов thisObject->CallbackMethod()
2) глобальную переменную еще можно держать в TLS
3) зоопарк переменных можно зашаблонить
typedef void(*ExtendedCallback)(void * internalState, Data * data, void* userData);
template <typename tag>
struct CallbackHolder
{
static void Func(void * internalState, Data * data)
{
UserCallback(internalState, data, UserData);
}
static void* UserData = nullptr;
static ExtendedCallback UserCallback = nullptr;
}
//usagestruct MyTag1 {} ;// create any number of tags
//probably, we need to define static datavoid* CallbackHolder<MyTag1>::UserData = nullptr;
ExtendedCallback CallbackHolder<MyTag1>::UserCallback = nullptr;
Callback<MyTag1> c; // track lifetime as needed
Callback fn = &Callback<MyTag1>::Func;
addCallback(state, fn);
4) заморачиваемся с динамическими колбеками-трамплинами. их можно поддерживать динамически или сразу выделить пул из 100 колбеков. рекомендую гуглить по словам trampoline, thunk
на этом форуме тоже замечательно гуглится: http://rsdn.ru/forum/cpp.applied/5116247.flat
суть thunk в том, что он содержит секцию для хранения void* (доп данных) + расширенный колбек и содержит ассемблерный код, который перевызывает расширенный кол-бек со всеми данными
метакод
typedef void(*ExtendedCallback)(void * internalState, Data * data, void* userData);
struct ThunkData
{
<executable code>
void* UserData;
ExtendedCallback UserCallback;
};
ThunkData* data = ...; <- get from pool or allocate somehow
data->UserData = myData;
data->UserCallback = mySuperCallback;
Callback fn = (Callback)(data); <--- pointer to executable code inside thunk
addCallback(state, fn);
есть предложения в стандарт языка добавить поддержку таких thunk (ссылку не могу найти)
успехов
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, AHOHUM, Вы писали:
AHO>>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так: AHO>>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
U>обычно в C библиотеках дают возможность просунуть void* userData, поищите внимательнее, либо сообщите название библиотеки, чтобы мы убедились
AHO>>Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
U>по задумке нельзя. лямбды можно скастить к указателю на функцию только если она не захватывает никаких переменных в контекст
AHO>>В чём загвоздка?
U>на самом деле ваша проблема довольно распространена и существует несколько подходов для ее решения U>1) заводим глобальную переменную, кладем туда this, пишем глобальную функцию, которая имеет сигнатуру Callback и которая при вызове сделает перевызов thisObject->CallbackMethod() U>2) глобальную переменную еще можно держать в TLS U>3) зоопарк переменных можно зашаблонить U>
U>typedef void(*ExtendedCallback)(void * internalState, Data * data, void* userData);
U>template <typename tag>
U>struct CallbackHolder
U>{
U> static void Func(void * internalState, Data * data)
U> {
U> UserCallback(internalState, data, UserData);
U> }
U> static void* UserData = nullptr;
U> static ExtendedCallback UserCallback = nullptr;
U>}
U>//usage
U>struct MyTag1 {} ;// create any number of tags
U>//probably, we need to define static data
U>void* CallbackHolder<MyTag1>::UserData = nullptr;
U>ExtendedCallback CallbackHolder<MyTag1>::UserCallback = nullptr;
U>Callback<MyTag1> c; // track lifetime as needed
U>Callback fn = &Callback<MyTag1>::Func;
U>addCallback(state, fn);
U>
U>4) заморачиваемся с динамическими колбеками-трамплинами. их можно поддерживать динамически или сразу выделить пул из 100 колбеков. рекомендую гуглить по словам trampoline, thunk U>на этом форуме тоже замечательно гуглится: http://rsdn.ru/forum/cpp.applied/5116247.flat
U>суть thunk в том, что он содержит секцию для хранения void* (доп данных) + расширенный колбек и содержит ассемблерный код, который перевызывает расширенный кол-бек со всеми данными U>метакод U>
U>typedef void(*ExtendedCallback)(void * internalState, Data * data, void* userData);
U>struct ThunkData
U>{
U> <executable code>
U> void* UserData;
U> ExtendedCallback UserCallback;
U>};
U>ThunkData* data = ...; <- get from pool or allocate somehow
data->>UserData = myData;
data->>UserCallback = mySuperCallback;
U>Callback fn = (Callback)(data); <--- pointer to executable code inside thunk
U>addCallback(state, fn);
U>
U>есть предложения в стандарт языка добавить поддержку таких thunk (ссылку не могу найти) U>успехов
К сожалению, библиотека коммерческая, и мне категорически намекнули никуда её не выкладывать.
Внимательно поискал: ни в internalState, ни в data – нет места для сохранения указателя на объект класса. internalState имеет комментарий "internally used data" (и оно действительно так и есть, если более детально взглянуть на данную структуру), data содержит строго типизированные данные, которые ожидаются от библиотеки.
1) Вот от этого и хотел уйти, т.к. думал, что есть более "красивые" методы решения данной проблемы.
2) Тоже рассматривал как вариант.
3) Видимо это и буду использовать.
3) Да, конечно, я предварительно загуглил данную тему здесь, нашёл замечательную статью 2004 года. Просто вполне отдавал себе отчёт, что к 2015 году уже что-то есть в стандарте, что я мог запросто пропустить. В моём случае это будет из пушки по воробьям.
Спасибо за развернутый ответ, думаю, я определился с вариантом.
Здравствуйте, fdn721, Вы писали:
F>Здравствуйте, AHOHUM, Вы писали:
AHO>>В чём загвоздка?
F>В том что лямбда и бинд создают функциональные объекты. И использовать их может только код, который умеет работать с функциональными объектами. Так что ни как.
F>Что касается С колбек, то скорее всего в internalState есть место где хранить указатель на класс, вы его просто не нашли.
Спасибо, понял. Внимательно поискал: ни в internalState, ни в data – нет места для сохранения указателя на объект класса. internalState имеет комментарий "internally used data" (и оно действительно так и есть, если более детально взглянуть на данную структуру), data содержит строго типизированные данные, которые ожидаются от библиотеки.
Здравствуйте, VTT, Вы писали:
VTT>Здравствуйте, AHOHUM, Вы писали:
AHO>>Имеется С библиотека с неизменяемым интерфейсом
AHO>>В чём загвоздка?
VTT>std::bind возвращает совсем не Callback *, так что, если интерфейс библиотеки совсем не предполагает хранения указателей на некоторые пользовательские данные, то это придется делать самому. Например, можно держать в статическом поле класса ::std::map< /* internalState */ void *, Class * > и при вызове коллбэка находить соответствующий экземпляр класса.
Спасибо, так и хотел сделать, но думал, что есть более "красивые" методы решения данной проблемы.
AHO>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
1. Где создаётся и удаляется internalState? На нашей стороне?
2. В callback передаётся именно тот указатель internalState который был передан в addCallback?
I. Если на оба вопроса ответ да — то можно к нему прицепом нагрузить наши данные. То есть:
А callback будет доставать payload через offsetof.
II. Если ответ да только на второй вопрос — то можно создать отображение из *internalState в наши данные, например unordered_map<void*, OurData> — и callback будет знать из какой ячейки доставать payload.
AHO>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
Ещё, как вариант (если другие не подходят), можно прятать указатель/индекс данных в padding'е internalState — если конечно его достаточно, и он нигде не теряется/не затирается.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, AHOHUM, Вы писали:
AHO>>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так: AHO>>
AHO>>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
EP>1. Где создаётся и удаляется internalState? На нашей стороне? EP>2. В callback передаётся именно тот указатель internalState который был передан в addCallback?
EP>I. Если на оба вопроса ответ да — то можно к нему прицепом нагрузить наши данные. То есть: EP>
А callback будет доставать payload через offsetof.
EP>II. Если ответ да только на второй вопрос — то можно создать отображение из *internalState в наши данные, например unordered_map<void*, OurData> — и callback будет знать из какой ячейки доставать payload.
1) Объявлен как поле класса, создается посредствам create(&internalState, …) этой же библиотеки.
2) Да, именно он.
Сейчас сделано как раз на unordered_map с ключом internalState, разбираюсь с 3м методом предложенным товарищем uzhas'ом.
Здравствуйте, sokel, Вы писали:
S>Здравствуйте, uzhas, Вы писали:
U>>3) зоопарк переменных можно зашаблонить
S>Если с тегами, то можно так примерно через std::function:
О, а в качестве тега можно тип внешней функций запользовать:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, sokel, Вы писали:
U>>>3) зоопарк переменных можно зашаблонить S>>Если с тегами, то можно так примерно через std::function:
EP>std::function там не нужен.
std::funсtion зато не только thiscall, более универсальный.
EP>В качестве тэгов проще использовать числа чем типы. http://rsdn.ru/forum/cpp/5121566.1
Здравствуйте, sokel, Вы писали:
EP>>std::function там не нужен. S>std::funсtion зато не только thiscall, более универсальный.
Так я и не говорю что только thiscall — там может быть любой функциональный объект, что результат bind'а, что лямбда и т.п.
std::function нужен когда требуется стереть тип, а здесь же наоборот — чем конкретней тип, тем проще избежать коллизии.
EP>>В качестве тэгов проще использовать числа чем типы. http://rsdn.ru/forum/cpp/5121566.1
Одна проблема — это либо не компилируется / вылетает / либо статья старая, и автор не учитывает такую крутую штуку, как DEP.
А еще оно может съесть первый аргумент функции.
Не подскажет аль кто живой проект, и чтоб оно не съедало первый аргумент функции?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>std::function нужен когда требуется стереть тип, а здесь же наоборот — чем конкретней тип, тем проще избежать коллизии.
Да, согласен. Просто быстрый вариант отложенного конструктора вместо optional
Инты можно легко в теги завернуть если что, ну а сигнатуру то всё равно нужно отдельным параметром передавать.
Кстати, optional не съест noncopyable. Можно свой holder сделать, без требования copy-constructible:
Здравствуйте, sokel, Вы писали:
S>ну а сигнатуру то всё равно нужно отдельным параметром передавать.
Можно выводить — если конечно то что выведется устроит. Но вывод не всегда возможен, например с шаблонами или перегрузкой — так что тут зависит от ситуации, думаю явная сигнатура предпочтительней.
S>Кстати, optional не съест noncopyable.
Здравствуйте, beyv, Вы писали:
B>Здравствуйте, AHOHUM, Вы писали:
B>Рекомендую FastDelegate, сам много лет использую для колбеков всех мастей. B>Желательно прочитать статью чтобы понять как оно работает.
Да, именно про эту статью я и писал выше, тут даже есть перевод её здесь
Здравствуйте, AHOHUM, Вы писали:
AHO>Здравствуйте, beyv, Вы писали:
B>>Здравствуйте, AHOHUM, Вы писали:
B>>Рекомендую FastDelegate, сам много лет использую для колбеков всех мастей. B>>Желательно прочитать статью чтобы понять как оно работает.
AHO>Да, именно про эту статью я и писал выше, тут даже есть перевод её здесь
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Это как раз std::function noncopyable не съест — особенности type-erasure (тут как раз нужен специальный тип a-la move_function).
std::function это да, там копирование не выпиливается потому что виртуализируется.
EP>Почему? Судя по документации — должен: 1, 2.
А с boost — ну у меня, видимо, boost старый — 1.55. Но похоже ещё и у bind с move присваиванием проблемы могут быть...
Свой storage для функтора позволяет понизить требование с move-assignable до move-constructible.
Или я что то не так делаю?
#include <iostream>
#include <memory>
#include <boost/optional.hpp>
// примерный optional, присваивание через perfect forwardtemplate<typename T>
struct opt_move_assign {
~opt_move_assign() {
if(constructed)
reinterpret_cast<T*>(&data)->~T();
}
template<typename U>
opt_move_assign& operator=(U&& x) {
if(constructed)
*(reinterpret_cast<T*>(&data)) = std::forward<U>(x);
else {
new (&data) T(std::forward<T>(x));
constructed = true;
}
return *this;
}
bool constructed = false;
typename std::aligned_storage<sizeof(T)>::type data;
};
// примерный optional, присваивание не используетсяtemplate<typename T>
struct opt_move_construct {
~opt_move_construct() {
if(constructed)
reinterpret_cast<T*>(&data)->~T();
}
template<typename U>
opt_move_construct& operator=(U&& x) {
if(constructed) {
constructed = false;
reinterpret_cast<T*>(&data)->~T();
}
new (&data) T(std::forward<T>(x));
constructed = true;
return *this;
}
bool constructed = false;
typename std::aligned_storage<sizeof(T)>::type data;
};
template<template<class> class Storage, class F>
void test(F&& f) {
using store_type = std::decay<F>::type;
Storage<store_type> x;
x = std::forward<F>(f);
}
struct foo {
void bar() {}
};
int main() {
// вот это ок, компилится
test<opt_move_assign>(std::make_unique<int>(111));
test<opt_move_construct>(std::make_unique<int>(111));
// вот это уже нет (boost 1.55)
// test<boost::optional>(std::make_unique<int>(111));
// а вот тут уже bind, вылезает copy tuple
// test<opt_move_assign>(std::bind(&foo::bar, std::make_unique<foo>()));
// хотя через move-construct всё ok
test<opt_move_construct>(std::bind(&foo::bar, std::make_unique<foo>()));
// ну как и в предыдушем варианте, тоже беда...
// test<boost::optional>(std::bind(&foo::bar, std::make_unique<foo>()));return 0;
}
Здравствуйте, sokel, Вы писали:
S>Но похоже ещё и у bind с move присваиванием проблемы могут быть... S>Свой storage для функтора позволяет понизить требование с move-assignable до move-constructible. S>Или я что то не так делаю?
А, ну собственно по стандарту никто и не требует от bind быть MoveAssignable:
The return type shall satisfy the requirements of MoveConstructible. If all of FD and TiD
satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements
of CopyConstructible. [ Note: This implies that all of FD and TiD are MoveConstructible. — end
note ]
Здравствуйте, Zenden, Вы писали:
Z>Разве оно умеет "Метод класс как С колбек" ?
Да, умеет (если вставить недостающие буквы в "Метод класс как С колбек" )
там есть примеры в FastDelegateDemo.cpp
примерно так
using namespace fastdelegate;
// Это классclass CClass {
public:
// Это метод классаint Function(int num, char *str);
};
int main(void){
// Обьявляете тип делегата (параметр1, параметр2, тип результата)typedef FastDelegate2<int, char *, int> FunctionDelegate;
// Создаете класс
CClass a();
// "deleg" - переменная-колбек, цепляем на неё метод класса
FunctionDelegate deleg = MakeDelegate(&a, &CClass::Function);
// вызываем метод класса как простую функциюint ret = deleg(5, "foo");
}
Здравствуйте, beyv, Вы писали:
B>Здравствуйте, Zenden, Вы писали:
Z>>Разве оно умеет "Метод класс как С колбек" ?
B>Да, умеет (если вставить недостающие буквы в "Метод класс как С колбек" )
B>там есть примеры в FastDelegateDemo.cpp
Неа, не умеет. Задачу автора (и мою) не решает.
У fastdelegate просто перегружен operator(), а нужен простой указатель на фукнцию.
Здравствуйте, Zenden, Вы писали:
Z>Неа, не умеет. Задачу автора (и мою) не решает. Z>У fastdelegate просто перегружен operator(), а нужен простой указатель на фукнцию.
Даа, умеет. Задача автора: "Метод класс как С колбек" а не "простой указатель на фукнцию"
Переменную "FunctionDelegate deleg" (из примера) можно использовать как угодно — брать адрес, передавать как параметр, запускать в космос...
Если "задача" у вас поизвращатся и пытатся изобрести велосипед, ну чтож...
Здравствуйте, beyv, Вы писали:
B>Здравствуйте, Zenden, Вы писали:
Z>>Неа, не умеет. Задачу автора (и мою) не решает. Z>>У fastdelegate просто перегружен operator(), а нужен простой указатель на фукнцию.
B>Даа, умеет. Задача автора: "Метод класс как С колбек" а не "простой указатель на фукнцию" B>Переменную "FunctionDelegate deleg" (из примера) можно использовать как угодно — брать адрес, передавать как параметр, запускать в космос... B>Если "задача" у вас поизвращатся и пытатся изобрести велосипед, ну чтож...
На этом, как вы говорите, "извращении" немало библиотек построено — например ATL, WTL.
Задача дана вполне конкретная, общего решения так и не предложено.
fastdelegate хорошая вещь, я ее использую в своих проектах, но в данном случае она приведена не к месту.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, beyv, Вы писали:
B>>Даа, умеет. Задача автора: "Метод класс как С колбек" а не "простой указатель на фукнцию"
EP>Прочитай изначальное сообщение, а не только его заголовок.
Прочитайте исходные код FastDelegate, прежде чем умничать.
Основная загвоздка у ТС получения доступа к полям класса в теле колбека или где там.
Пожалуйста, получите от делегата указатель "This", приведите его к классу и вот вам класс
#include"stdafx.h"#include"FastDelegate.h"using namespace fastdelegate;
// Это классclass CClass {
protected:
char *m_name;
public:
CClass(char *name) : m_name(name) {};
// Это метод классаint Function(int num, char *str) {
printf("In Function in %s. Num=%d, str = %s\n", m_name, num, str); return -1;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef FastDelegate2<int, char *, int> FunctionDelegate;
// Создаете класс
CClass a("Base A");
// "deleg" - переменная-колбек
FunctionDelegate deleg;
// цепляем на неё метод класса и можем передать его куда угодно
deleg = MakeDelegate(&a, &CClass::Function);
// можем использовать как функцию
deleg(7, "tr");
// Чуть поизвращаясь, можно получить указатель на сам классconst detail::ClosurePtr<int, char *, int>& p = (const detail::ClosurePtr<int, char *, int>&)deleg.GetMemento();
CClass* ap = (CClass*)p.GetClosureThis();
// Получили класс со всеми потрохами
ap->Function(77, "ааааа");
return 0;
}
Здравствуйте, beyv, Вы писали:
B>>>Даа, умеет. Задача автора: "Метод класс как С колбек" а не "простой указатель на фукнцию" EP>>Прочитай изначальное сообщение, а не только его заголовок. B>Прочитайте исходные код FastDelegate,
И в чём там принципиальное отличие от std::function в рамках вопроса ТС?
B>прежде чем умничать.
О, вот уже и хамство пошло в ход — классный аргумент, главное универсальный
B>Основная загвоздка у ТС получения доступа к полям класса в теле колбека или где там. B>Пожалуйста, получите от делегата указатель "This", приведите его к классу и вот вам класс
И что это даст в случае ТС?
AHO>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так:
AHO>
Здравствуйте, beyv, Вы писали:
EP>>И в чём там принципиальное отличие от std::function в рамках вопроса ТС? B>FastDelegate инкапсулирует в себе и "this" и "метод класса"
Точно также как и std::function + std::bind, только проблему ТС это никак не решает
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, beyv, Вы писали:
EP>>>И в чём там принципиальное отличие от std::function в рамках вопроса ТС? B>>FastDelegate инкапсулирует в себе и "this" и "метод класса"
EP>Точно также как и std::function + std::bind, только проблему ТС это никак не решает
Ну вы даете, я вам нарисовал как сделать делегата(колбек) на экземпляр любого класса и любой его метод(хоть с 6 параметрами),
как передать его в "void addCallback(void * internalState, Callback * callback);" вместо "callback"
как извлечь из переданого делегата экземпляр переданого класса и делать с ним что угодно
и это не решает проблему ТС ?
Боюсь даже спрашивать какая ещё тут проблема, кривые руки? непонимание чужого кода?
Здравствуйте, beyv, Вы писали:
EP>>>>И в чём там принципиальное отличие от std::function в рамках вопроса ТС? B>>>FastDelegate инкапсулирует в себе и "this" и "метод класса" EP>>Точно также как и std::function + std::bind, только проблему ТС это никак не решает B>Ну вы даете, я вам нарисовал как сделать делегата(колбек) на экземпляр любого класса и любой его метод(хоть с 6 параметрами), B>как передать его в "void addCallback(void * internalState, Callback * callback);" вместо "callback"
Этот callback будет использоваться внутри именно как указатель на функцию (то есть будет совершён вызов кода по этому адресу), вместо которого ты пытаешься передать указатель на экземпляр класса FastDelegate.
То есть получается что-то типа: LIVE DEMO