我正在编写一个带有托管C ++包装器的本机C ++项目,它可以从C#接收和调用回调。托管方也应该能够在托管环境中检索回调和触发器。
上述回调的签名是:
// Native C++
typedef EvaluateResult (*NativeFunction) (std::vector<EvaluateResult> args);
// Managed C++ wrapper
delegate EvaluateResultWrapper^ ManagedFunction (List<EvaluateResultWrapper^> args);
EvaluateResultWrapper
是本机类EvaluateResult
的托管包装类。 EvaluateResult
之间的转换是:
EvaluateResult result;
EvaluateResultWrapper^ wrapper = gcnew EvaluateResultWrapper (result);
result = EvaluateResult (*wrapper.original);
我想实现构造函数EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func)
,它可以粗略地执行以下操作:
// NOTE: Pseudo code
void EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func) {
this->func = func; // Store the func as a member to avoid GC
// original is the pointer to the EvaluateResult that this object is wrapping around
this->original = new EvaluateResult ([&func](std::vector<EvaluateResult> args) -> EvaluateResult {
List<EvaluateResultWrapper^>^ argsList; // Convert args from vector to List. Assuming it is done under the hood
EvaluateResultWrapper^ wrapper = func->Invoke (argsList); // Invoke the managed callback
return EvaluateResult (wrapper.GetOriginal ()); // Convert the managed result to the native counterpart
});
}
我知道上面的代码不起作用,但是我应该能够使用能够转换回调参数和返回类型<的代码包装托管回调的想法/ em>,因此原生友好。
理想情况下,我也可以采取相反的方式(不重要)
// NOTE: Pseudo code
ManagedFunction^ EvaluateResultWrapper::GetFunction (ManagedFunction^ func) {
// if the callback is set by the managed side, return the same callback back
if (this->func != nullptr) return this->func;
// Otherwise, the callback is a native one
NativeFunction nativeFunc = this->original->GetFunction ();
return gcnew ManagedFunction ([&nativeFunc] (List<EvaluateResultWrapper^>^ args) -> EvaluaResultWrapper {
std::vector argsList; // Convert the args from List back to vector. Assuming it is done under the hood
EvaluateResult result = nativeFunc (argsList); // Invoke the native function
return gcnew EvaluateResultWrapper (result); // Convert the native result into the managed one
});
}
我想知道这是否可以做到?
一点上下文:我正在为我们的游戏在本机C ++上编写外部脚本系统(类似于Lua脚本)。 EvaluateResult
是表示任何语句的评估结果的类。它基本上是一个与类型相结合的值。类型可以是数字,布尔值,字符串,数组,对象,或者在这种情况下:函数回调。
函数回调可以在本机C ++中设置(当解释器在脚本中传递用户定义的函数时)或由主机(管理端)设置的函数。
主意(C#端)应该能够在内存中定义和设置函数(例如,定义print()
函数以打印到主机控制台中)。在存储到脚本存储器之前,回调被包装为EvaluateResult
类。
出于检查目的,C#端必须能够获得函数回调。因此,获得该功能的能力很好(但并不重要,因为我总是可以指示本机方为我执行该功能)