C++和C#之间互相调用经验详谈
作者:网络转载 发布时间:[ 2014/1/23 9:28:24 ] 推荐标签:C++ C#
当然了,在建项目时,项目类型要为类库。至此类库部分已经完毕。接下来再看看主程序如何加载,以及如何调用把。
其中在动态创建时,ProgId是关键。这一部分对搞过COM,在加上ATL的人来说,可能太简单了,‘可能’这个词也许用的不太恰当,因为她不是‘可能’,她确实简单。不信看代码。
::CoInitialize(NULL);
const OLECHAR lpszProgID[]=OLESTR("xxxxxxx.xxxxxxx"); //ProgID
CComPtr m_NetCustomer;
HRESULT hr = m_NetCustomer.CoCreateInstance(lpszProgID);
if(SUCCEEDED(hr))
{
const LPCOLESTR szMember=OLESTR("OnCreate");
VARIANT v;
v.vt = VT_I4; v.lVal = 1024;
hr = m_NetCustomer.Invoke1(szMember,&v);
if(SUCCEEDED(hr))
{
}
}
::CoUninitialize();
怎么样?没有撒谎把,几行代码把创建、调用搞定了。
郁闷,从C++拷出来代码没有格式,还的手工加。。。。
2. 回调 即子调父。
主程序肯定按照自己的逻辑顺序依次调用子模块的接口,如先创建、子的相关逻辑、后销毁。如果说在实际运用中,子模块完全不会在调用父的相关功能,那么此时框架已经完全实现了,我们之前做的工作是。难道不是吗?,但应用程序往往也有父与子相互调用,下面来看看,子如何回调父的功能把
前面也说过,子调父往往是这样,从父身上分离出部分代码,重新封装一个dll,由子静态绑定,这步简单、方便。不过这显然不是正道,让人觉得别扭。
同时维护两份相同功能代码? 也许你会说,主程序从此也可以调用DLL啊,那不一致了,你要真这样说,我的回答是,“我只是在说明问题,不涉及到架构问题”
还有每个子模块都静态绑定这个DLL?
还有你在分离这个DLL时,如果依赖主程序太多,你怎么办?
还有你能保证分离后的稳定性吗?回带来其他的问题吗?
还有你仅仅是为了满足功能,才这样做的?
你觉得这样看着顺眼吗?
等等。反正我觉得是古怪之急。
接下来要需找其他替代方案了。
先考虑下在C++中这一部分是如何实现的把。 父传给子一个虚接口(虚类),子在适当的时候调用。仅此而已。让我们把调用函数想的深入一点。直接看汇编代码把。
看代码之前,还要先简单说一下函数调用相关信息。在汇编层调用一个函数无非也是JMP、CALL 之类的指令,若函数还有参数是一些PUSH指令。好了知道这些足够了,下面看看在VC中的伪代码。
__asm
{//类虚函数的汇编模拟调用,函数无参数、无返回值。
mov eax,xxxxx //存放函数地址
mov ecx,xxxxx //this指针
call eax //调用
}
这样调用完成了,其实真正的调用也如此,只不过指令多几条而已。因为她要得到某些信息。
好了,如果说.NET支持内敛汇编,那我们完全可以自己模拟虚函数调用,不用在封装什么DLL,这所有的一切都可以搞定,但可惜的时,常规下内敛汇编是不支持的。不错,我说的是常规,那非常规呢?答案是肯定的。
关于内敛汇编网上也是一大片,底层思想是,在内存开辟一段空间,并放入相应指令,到时侯执行这一部分逻辑即可,这样可以完成内敛汇编了。
其中网上有一个封装好的DLL(AsmClassLibrary.dll),提供接口编写汇编代码,用Reflector 查看了发现其后执行采用远程线程注入方式,对于嵌入一两个模块的,可以这样做,但如果模块很多的话,毕竟注入涉及到安全的问题,这一点不太好,当然这也太另类了,我可不想应用程序到处以这种方式来执行。
所以我们采用Marshal.GetDelegateForFunctionPointer方式。
因为从底层上讲,是不分什么语言编写,只认机器指令的,因此只要我们模拟的合理、正确,这一点是没有问题的。
好了,现在我们目标很明确,用内敛方式在C#模拟虚函数的调用。
在给出代码之前,也先说下思路。
根据之前所讲以及常规知识,以下几点是必须的。
A 类对象指针,因为我们要将此值给ECX。
B 成员函数地址,当然了,我们要CALL嘛。
C 参数,这值是在C#中使用的。
这是主要内容,实现他们方式有很多种,以下是我的方案。
因为接口会很多,因此我将this指针、函数地址都放到数组中,然后在传递给C#中,其实按道理说,只传递一个this指针够了,其他部分应该在C#中实现,但操作指针C++中比较简便,所以这部分代码在C++中做了。
得到this指针 太简单啦,根据虚表布局得到其地址也很简单。如下。
接口定义如下。
class CInterface
{
public:
virtual void test1( LPSTR p)
virtual void test2();
virtual void test3( int a);
};
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11