设为首页 加入收藏

TOP

C++和C#之间互相调用经验详谈(四)
2014-02-08 13:37:06 来源: 作者: 【 】 浏览:467
Tags:之间 互相 调用 经验 详谈

 

  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);

  };

  得到this指针及成员函数地址。

  CInterface *pInterface = new CInterface;

  DWORD base_proc = (*((DWORD *)(pInterface))); //虚表指针

  DWORD f1 = *(( DWORD *)base_proc); //第1个

  DWORD f2 = *(( DWORD *)(base_proc + 4)); //第2个

  DWORD f3 = *(( DWORD *)(base_proc + 8)); //第三个

  到时将值赋值到SAFEARRAY 安全数组中,在传递到C#中。

        

首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++编译链接的那些小事 下一篇一道H-number 数论实例

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Libevent C++ 高并发 (2025-12-26 00:49:30)
·C++ dll 设计接口时 (2025-12-26 00:49:28)
·透彻理解 C 语言指针 (2025-12-26 00:22:52)
·C语言指针详解 (经典 (2025-12-26 00:22:49)
·C 指针 | 菜鸟教程 (2025-12-26 00:22:46)