Сообщение Re: Метод класс как С колбек от 09.04.2015 9:51
Изменено 09.04.2015 10:04 uzhas
Здравствуйте, AHOHUM, Вы писали:
AHO>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так:
AHO>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
обычно в C библиотеках дают возможность просунуть void* userData, поищите внимательнее, либо сообщите название библиотеки, чтобы мы убедились
AHO>Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
по задумке нельзя
AHO>В чём загвоздка?
на самом деле ваша проблема довольно распространена и существует несколько подходов для ее решения
1) заводим глобальную переменную, кладем туда this, пишем глобальную функцию, которая имеет сигнатуру Callback и которая при вызове сделает перевызов thisObject->CallbackMethod()
2) глобальную переменную еще можно держать в TLS
3) зоопарк переменных можно зашаблонить
4) заморачиваемся с динамическими колбеками-трамплинами. их можно поддерживать динамически или сразу выделить пул из 100 колбеков. рекомендую гуглить по словам trampoline, thunk
на этом форуме тоже замечательно гуглится: http://rsdn.ru/forum/cpp.applied/5116247.flat
суть thunk в том, что он содержит секцию для хранения void* (доп данных) + расширенный колбек и содержит ассемблерный код, который перевызывает расширенный кол-бек со всеми данными
метакод
успехов
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;
}
//usage
struct MyTag1 {} ;// create any number of tags
//probably, we need to define static data
void* 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
Автор: uzhas
Дата: 28.03.13
Дата: 28.03.13
суть 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);
успехов
Re: Метод класс как С колбек
Здравствуйте, AHOHUM, Вы писали:
AHO>Имеется С библиотека с неизменяемым интерфейсом, одна из функций выглядит так:
AHO>internalState – сугубо внутренняя структура библиотеки, data – данные получаемые из библиотеки, т.е. никаких void * userData нет.
обычно в C библиотеках дают возможность просунуть void* userData, поищите внимательнее, либо сообщите название библиотеки, чтобы мы убедились
AHO>Не могу понять, возможно ли здесь воспользоваться лямбдой или bind(оба параметра: internalState, data — должны быть доступны):
по задумке нельзя. лямбды можно скастить к указателю на функцию только если она не захватывает никаких переменных в контекст
AHO>В чём загвоздка?
на самом деле ваша проблема довольно распространена и существует несколько подходов для ее решения
1) заводим глобальную переменную, кладем туда this, пишем глобальную функцию, которая имеет сигнатуру Callback и которая при вызове сделает перевызов thisObject->CallbackMethod()
2) глобальную переменную еще можно держать в TLS
3) зоопарк переменных можно зашаблонить
4) заморачиваемся с динамическими колбеками-трамплинами. их можно поддерживать динамически или сразу выделить пул из 100 колбеков. рекомендую гуглить по словам trampoline, thunk
на этом форуме тоже замечательно гуглится: http://rsdn.ru/forum/cpp.applied/5116247.flat
суть thunk в том, что он содержит секцию для хранения void* (доп данных) + расширенный колбек и содержит ассемблерный код, который перевызывает расширенный кол-бек со всеми данными
метакод
есть предложения в стандарт языка добавить поддержку таких thunk (ссылку не могу найти)
успехов
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;
}
//usage
struct MyTag1 {} ;// create any number of tags
//probably, we need to define static data
void* 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
Автор: uzhas
Дата: 28.03.13
Дата: 28.03.13
суть 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 (ссылку не могу найти)
успехов