当我们学会了使用C++调用C#,也学会注入回调函数到C#中之后,下一步,也是最重要的事就是,把我们的托管C++
封装为一个C++
的接口,提供给Native C++
使用。
这里我们需要使用一种名为Pimpl
的编程思想。
Pimpl
的思想如下图所示:
简要的说,我们需要将所有的细节隐藏起来,暴露给外面的,仅仅有行为接口。在CPP实现中,我们可以做任何事情,但是对一切引用我们的头文件的类而言,我们的类都是一个普通的C++
头文件。这样的话,我们可以使用Cli
来实现调用C#
,又可以暴露出一个Native C++
的接口。
简要的说下实现方式。这里需要绕一个很大的圈,这样会带来极大的性能损失,所以C++
调用C#
,除非是项目历史包袱,一般情况下,我们是不会这样使用的。
我们先用托管C++
类,在其中实现调用C#
的代码。而后这个类作为接口私有类的成员变量使用。接口类使用接口私有类来完成工作。
我们需要使用一个这么长的调用链,才能成功的从接口类调用到C#
代码。
此外,我们需要注意到,这里的pimpl
私有类,也是一个Native C++
。这就带来了一个悖论,在Native C++
中,我们不能使用托管C++
句柄。所以,需要使用一些小工具来帮助我们实现在Native C++
中封装托管C++
#include //gcroot
using namespace msclr; // gcroot
在这一个头文件中,有一个模板类gcroot
,该类能够在Native C++
包装我们需要的句柄。
具体的使用方法如下述代码所示:
public ref class Handle {
Handle(System::String ^);
handleUse();
};
class Native {
Native();
void use();
public:
gcroot< Handle ^ > handle;
};
我们存在着Handle
这么一个托管类,在Native C++
中,直接将其作为类型来看待即可。
使用方式如下所示:
Native::Native() {
handle = gcnew Handle ("aaaa");
}
void Native::use() {
handle->handleUse();
}
这里因为也是在CPP
文件中,所以我们可以在函数中使用gcnew
等各种托管C++
的东西,但是在声明时,却不可以!
经过这样的方式,我们就可以自由的使用C++
去调用各类C#
的特性了。