使用托管参数传递回调并在托管和非托管C ++之间返回类型

时间:2017-05-30 16:46:10

标签: c++-cli

我正在编写一个带有托管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#端必须能够获得函数回调。因此,获得该功能的能力很好(但并不重要,因为我总是可以指示本机方为我执行该功能)

0 个答案:

没有答案