c++ - C++ 通用回调实现
问题描述
我有一个代码,它以 XML 的形式从 flash player 获取消息,将它们解析为函数和参数,并为该函数调用注册的回调。我要替换的那段代码做得很好(几乎)通用回调机制: flashSDK (ASInterface.inl) 的通用回调实现的代码。
问题在于这段代码是为闪存编写的,我想替换闪存并使用具有相同接口的其他服务。这种回调机制是否有任何标准实现(std?boost?其他开源的东西?)?
此代码实现了通用回调机制,您可以在映射中注册具有多个参数和类型的函数:
void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks["SomethingHappened"] = &SomethingHappened;
callbacks["SomethingElseHappened"] = &SomethingElseHappened;
而不是搜索它并使用一组参数调用:
Callbacks::iterator itCallback = callbacks.find(functionName);
if (itCallback != callbacks.end())
{
HRESULT result = itCallback->second.Call(arguments, returnValue);
}
完整使用示例:
//init callbacks
std::map<std::wstring, Callback> callbacks;
void SomethingHappened(int a, int b) {print a + b;}
void SomethingElseHappened(string abcd) {print abcd;}
callbacks[functionName] = &SomethingHappened;
void MessageArrived(string xmlInput)
{
string functionName = parseFunctionName(xmlInput);
Callbacks::iterator itCallback = callbacks.find(functionName);
if (itCallback != callbacks.end())
{
//parse arguments
std::vector<std::wstring> args;
_Args::split(xml, args);
ASValue::Array arguments;
for (size_t i = 0, s = args.size(); i < s; ++i)
{
ASValue arg; arg.FromXML(args[i]);
arguments.push_back(arg);
}
ASValue returnValue;
//***this is where the magic happens: call the function***
HRESULT result = itCallback->second.Call(arguments, returnValue);
return result;
}
}
解决方案
您可能需要一个包装器std::function
,例如:
template <typename T> struct Tag{};
// Convert ASValue to expected type,
// Possibly throw for invalid arguments.
bool Convert(Tag<Bool>, AsValue val) { return (Boolean)val; }
int Convert(Tag<int>, AsValue val) { return (Number)val; }
// ...
struct Callback
{
private:
template <std::size_t ... Is, typename Ret, typename ... Ts>
static Ret call_impl(Ret(* func)(Ts...), std::index_sequence<Is...>)
{
if (arr.size() != sizeof...(Is)) throw std::invalid_argument{};
return func(Convert(tag<Ts>{}, arr[Is])...);
}
public:
template <typename Ret, typename ... Ts>
Callback(Ret(* func)(Ts...)) : Call{[func](ASValue::Array arr, ASValue& ret)
{
try
{
ret = Callback::call_impl(func, std::make_index_sequence<sizeof(...(Ts)>());
return S_OK;
} catch (...) {
return E_INVALIDARG;
}
}}
{}
std::function<HRESULT(ASValue::Array, ASValue&)> Call;
};
std::index_sequence
是 C++14,但您可能会在 SO 上找到实现。
推荐阅读
- javascript - 元素类型无效:应为字符串 您可能忘记从定义组件的文件中导出组件?
- r - 如何根据 R 中的属性删除 SpatialPolygonsDataFrame 的特定特征?
- mysql - 为什么当两个人使用带有mysql的express api时,它给出了空响应,它没有崩溃但没有给出响应
- c++11 - 检查 << 运算符是否适用于覆盖模板上下文
- matlab - 谁能帮我解决有关 DPARSF 的问题?
- r - 泛化 data.frame 子集函数
- spring-webflux - 如何为 Spring Webflux WebClient (ReactorClientHttpConnector) 设置授权代理?
- javascript - 使用 getelementid 更改 SVG 过滤器
- java - java.lang.RuntimeException:RESTEASY003940:无法实例化 MessageBodyReader
- java - Java 命令行参数:简单打印不适用于“@%&^%”(不带引号)。请解释