Для обратного вызова требуется константная функция, как передать член экземпляра объекта

Я использую WebKitGTK+ в более крупном приложении GTKmm/C++. Я использую JavaScriptCore для взаимодействия с WebKitWebFrame и JContext внутри.

Теперь я застрял, так как мне нужно взаимодействовать с компонентом графического интерфейса GTK при вызове функции javascript. С этой целью я нашел JSObjectMakeFunctionWithCallback.

JSStringRef str = JSStringCreateWithUTF8CString("ClickCallback");
JSObjectRef func = JSObjectMakeFunctionWithCallback(m_jsRef, str, ClickCallback);
JSObjectSetProperty(m_jsRef, JSContextGetGlobalObject(m_jsRef), str, func, kJSPropertyAttributeNone, NULL);
JSStringRelease(str);

Где обратный вызов должен быть определен как статическая функция с def:

static JSValueRef ClickCallback(JSContextRef ctx, JSObjectRef func, JSObjectRef self, size_t argc, const JSValueRef argv[], JSValueRef* exception)

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

На SO есть множество подобных вопросов, но большинство из них сосредоточено на передаче экземпляра объекта в обратный вызов. Я не вижу способа сделать это с помощью этого API.

Любые идеи?


person Mark    schedule 10.09.2011    source источник
comment
Это не обязательно должна быть статическая функция или даже функция-член.   -  person Seth Carnegie    schedule 10.09.2011
comment
Я ненавижу, когда API позволяют вам зарегистрировать обратный вызов, не позволяя вам передать какой-либо контекстный файл cookie (обычно это void*).   -  person Emile Cormier    schedule 10.09.2011
comment
@Эмиль -- Точно. V8 позволяет это сделать путем присоединения специального указателя Data к объекту Arguments, который, по крайней мере, передается функции. Спасает от стольких хлопот.   -  person namuol    schedule 18.08.2013


Ответы (1)


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

JSValueRef ClickCallback(...)
{
  Foo & obj = getInstance(); // implement this somehow
  return obj.click(...);
}

В качестве альтернативы вы можете сделать это статической функцией-членом вашего класса GUI. Суть в том, что вы должны получить ссылку на экземпляр отдельно и вызвать функцию-член самостоятельно, если вам нужно передать простой указатель функции в ваш API.

person Kerrek SB    schedule 10.09.2011
comment
@Керрек СБ, спасибо. Вот так я и поступал. Я надеялся на какое-то волшебство, хотя оно сделает его немного чище... - person Mark; 10.09.2011