一个c++ signals2槽回调可以包含Objective-C/ c++类/选择器(方法)信息吗?
Can a C++ signals2 slot callback contain Objective-C/C++ Class/Selector (Method) information?
这对你们中的一些人来说肯定是显而易见的,但我找不到这样的例子:
我需要一个boost::signals2信号来连接一个槽回调,这是一个c++类成员函数或函子,所以我可以使模型回调到Objective-C/c++控制器代码。
该回调需要存储一个Objective-C/c++方法实例的Class和Selector,该实例可以在c++回调函数中调用。(我假设没有可能的方法来实际提供一个Objective-C/c++方法的直接回调函数地址)。我假设我需要创建一个c++类/函函数的实例来包含调用Objective-C/c++方法的信息。
我也不确定是否可以分离出类和SEL(选择器),并将它们存储在c++类的实例中进行回调,而不将它们作为void*传递。一旦c++回调被signal()调用,我希望可以用class_getInstanceMethod和method_getImplementation将它们转换为可用的(可调用的)形式。
另外,我可能想要从信号发送至少一个带有任意结构体("EventInfo")的参数到插槽,它可以提供有关信号性质的信息。
谁能给黑暗点光?花了我很长时间,但我终于弄明白了。可能有更简单的方法来做到这一点,但我发现我需要在.mm文件中创建一个c++类,作为boost::signals2信号和Objective-C回调函数之间的桥梁:
在CPPToCocoaModelMessageCallbacks.h:/* ------------------------------------------------------------------------
class CPPToCocoaModelMessageCallback -
--------------------------------------------------------------------------- */
class CPPToCocoaModelMessageCallback
{
public:
CPPToCocoaModelMessageCallback( PMD_Signal_Messenger<PrefEvent> *theSignalClass,
int whichPrefIdxToObserve,
id pObjCClass,
SEL pObjCMethod);
~CPPToCocoaModelMessageCallback();
void CallBackMessage(PrefEvent* pPrefEvent);
private:
id fpObjCClass;
SEL fpObjCMethod;
ls_index fWhichPrefIdxToObserve;
boost::signals2::connection fTheConnection;
}; // CPPToCocoaModelMessageCallback
在CPPToCocoaModelMessageCallbacks.mm /* ------------------------------------------------------------------------
CPPToCocoaModelMessageCallback - CONSTRUCTOR
whichPrefIdxToObserve - the preference idx to observe
Pass the id and selector of the Objective-C/C++ object & method to be
called.
--------------------------------------------------------------------------- */
CPPToCocoaModelMessageCallback::CPPToCocoaModelMessageCallback(PMD_Signal_Messenger<PrefEvent> *theSignalClass, int whichPrefIdxToObserve, id pObjCClass, SEL pObjCMethod)
: fpObjCClass (pObjCClass),
fpObjCMethod (pObjCMethod),
fWhichPrefIdxToObserve (whichPrefIdxToObserve)
{
fTheConnection = theSignalClass->ObserveSignal(&CPPToCocoaModelMessageCallback::CallBackMessage, this);
}
/* ------------------------------------------------------------------------
~CPPToCocoaModelMessageCallback - DESTRUCTOR
Pass the id and selector of the Objective-C/C++ object & method to be
called.
--------------------------------------------------------------------------- */
CPPToCocoaModelMessageCallback::~CPPToCocoaModelMessageCallback()
{
fTheConnection.disconnect();
}
/* ------------------------------------------------------------------------
CPPToCocoaModelMessageCallback::CallBackMessage -
Handles single and range-type preference change events.
--------------------------------------------------------------------------- */
void CPPToCocoaModelMessageCallback::CallBackMessage(PrefEvent* pPrefEvent)
{
// Only make the callback if this event is the preference we're observing
if (pPrefEvent->GetChangedPrefIdx() == fWhichPrefIdxToObserve) {
[fpObjCClass performSelector:fpObjCMethod];
}
}
///////////////////////////////////////////////////////////////////////////////
In your controller.mm:
// set up messaging from Model. The message callback functions must be destructed in dealloc.
// I've done this in awakeFromNib but it could be elsewhere
- (void)awakeFromNib {
PMD_Signal_Messenger<MyEventKind>* theModelClass = GetMyModelClassPointer();
displayMenuPrefChangedCallBack = new CPPToCocoaModelMessageCallback(theModelClass, kAppPrefDictionaryDisplayShortDef, self, @selector(displayMenuChanged));
}
/* ------------------------------------------------------------------------
displayMenuChanged - this gets called when the model fires a signal
(via CPPToCocoaModelMessageCallback::CallBackMessage())
--------------------------------------------------------------------------- */
- (void) displayMenuChanged
{
NSLog(@"displayMenuChangedn");
// DO SOMETHING TO RESPOND TO THE SIGNAL (in this case I'm reloading an NSWebView):
[self reloadWebViewText];
}
//////////////////////////////////////////////////////////////////////////////
与信令观察者的模型类相结合的类:
PMD_Signal_Messenger.h:
/* ------------------------------------------------------------------------
class PMD_Signal_Messenger<MyEventKind> -
This class is designed to be multiple inherited with various
Model classes.
--------------------------------------------------------------------------- */
template <class MyEventKind>
class PMD_Signal_Messenger {
public:
PMD_Signal_Messenger() { }
~PMD_Signal_Messenger() { }
template<typename Fn, typename Obj>
boost::signals2::connection ObserveSignal(Fn callback, Obj &object) {
return fSignalObservers.connect(boost::bind(callback, object, _1));
}
protected:
boost::signals2::signal<void (MyEventKind*)> fSignalObservers; // all observers of my preference changes
private:
PMD_Signal_Messenger(const PMD_Signal_Messenger& thePMD_Signal_Messenger) { assert(false); } // prevent copy constructor
};
在.cpp MODEL文件中,您想要发出模型更改的信号:
// construct theEvent (your own struct) and fire the signal with your event structure that gets passed to CPPToCocoaModelMessageCallback::CallBackMessage()
MyEventKind theEvent(someUsefulParams);
fSignalObservers(&theEvent);
您可以使用以下解决方案:https://github.com/godexsoft/objc_callback
#pragma once
#ifndef _OBJC_CALLBACK_H_
#define _OBJC_CALLBACK_H_
template<typename Signature> class objc_callback;
template<typename R, typename... Ts>
class objc_callback<R(Ts...)>
{
public:
typedef R (*func)(id, SEL, Ts...);
objc_callback(SEL sel, id obj)
: sel_(sel)
, obj_(obj)
, fun_((func)[obj methodForSelector:sel])
{
}
inline R operator ()(Ts... vs)
{
return fun_(obj_, sel_, vs...);
}
private:
SEL sel_;
id obj_;
func fun_;
};
#endif // _OBJC_CALLBACK_H_
- QT 样式表主题,适用于使用属性选择器的整个应用程序
- C++ gtkmm:文件选择器对话框不适用于任何驱动器
- 菜单选择器不接受有效输入
- Cocos2dx 如何在没有调度选择器的情况下每 5 秒调用一次函数
- 如何在Qt中创建自定义颜色选择器
- 随机数组选择器
- VTK抽象选择器,用于不同不透明度值的多个参与者
- Cocoa 选择器的行为可以在 C++ 中重新实现吗?
- 用模板基础编译时间类选择器
- 选择位掩码中与选择器位图中的1位重叠的设置位的跨度
- 用于 LINQ 静态方法的 C++/CLI Lambda 选择器
- 目标 c 将块转换为选择器
- C++11:根据项目计数在 std::array 和 std::unordered_map 之间实现选择器
- 使用 CSS (QSS) 选择器获取 QWidget*
- MFC日期时间选择器零值
- 为什么Qt不应用这个样式表类型选择器?
- igraph 中的即时选择器
- 计划选择器错误
- C++中的日期/时间选择器
- 带有人类可读选项选择器的c++类函数