zoukankan      html  css  js  c++  java
  • Win32C++调用C#(一):开篇

             Win32C++是非托管的,C#是托管的,不管出于什么目的,有时候需要在非托管的C++里调用现存的C#类库。我经常使用的方法是修改C# il 代码,然后重新编译il以供C++调用。
     有一段cs代码: 
     1 using System;
     2 
     3 namespace ManagedLib
     4 
     5 {
     6 
     7     public classExport
     8 
     9     {
    10         publics tatic int Add(int a, intb)//函数修饰符限定为public和static,这里是必须的
    11 
    12         {
    13 
    14             return a + b;
    15 
    16         }
    17 
    18     }
    19 
    20 }

    编译后生成ManagedLib.dll文件,用ildasm工具打开该文件,然后保存为ManagedLib.il文件,修改以下代码:

    .method public hidebysig static int32  Add(int32 a,
                                               int32 b) cil managed
    {
      // 代码大小       9 (0x9)
      .maxstack  2
      .locals init ([0] int32 V_0)
      IL_0000:  nop
      IL_0001:  ldarg.0
      IL_0002:  ldarg.1
      IL_0003:  add
      IL_0004:  stloc.0
      IL_0005:  br.s       IL_0007
      IL_0007:  ldloc.0
      IL_0008:  ret
    } 

    修改后的代码:

    .method public hidebysig static int32 modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) 
            Add(int32 a,
                int32 b) cil managed
    {
      .vtentry 1 : 1
      .export [0] as Add
      // 代码大小       9 (0x9)
      .maxstack  2
      .locals init (int32 V_0)
      IL_0000:  nop
      IL_0001:  ldarg.0
      IL_0002:  ldarg.1
      IL_0003:  add
      IL_0004:  stloc.0
      IL_0005:  br.s       IL_0007
      IL_0007:  ldloc.0
      IL_0008:  ret
    }

    用ilasm工具编译il文件,编译成功后.corflags 自动变成了0x00000002,同时增加了如下指令

    .vtfixup [1] int32 fromunmanaged at D_00004000
    .data D_00004000 = bytearray (05 00 00 06) 

     增加.vtfixup 和.data两条指令负是为了责非托管导出。
     现在,假设有x个函数,在需要导出的函数内部分别增加两条指令,其中,x对应要导出的函数个数

    .vtentry 1 : 2
    .export [1] as 函数名
    ......
    .vtentry 1 : x
    .export [x-1] as 函数名

    在C++中动态调用Add函数
            把ManagedLib.dll文件拷贝到C++应用程序目录,在C++文件中增加以下代码:

     1 typedef int(_stdcall  *Dllfun)(int,int);//必须设置_stdcall,否则运行时出错。
     2 
     3 void ManagedCall()
     4 
     5 {
     6          Dllfun addfun;
     7 
     8          HINSTANCE hdll;
     9 
    10          hdll= LoadLibrary(_T("ManagedLib.dll"));
    11 
    12          if(hdll != NULL)
    13 
    14          {
    15 
    16                    addfun= (Dllfun)GetProcAddress(hdll, "Add");
    17 
    18                    if(addfun != NULL) {               
    19 
    20                             int result = addfun(1, 2);
    21 
    22                             LPTSTR szBuffer = new TCHAR[100];
    23 
    24                             _snwprintf_s(szBuffer,100, 100, L"a+b:%d",result);
    25 
    26                             MessageBoxEx(NULL,szBuffer, _T("ManagedLib.dll"),0, 0);
    27 
    28                    }
    29 
    30                    FreeLibrary(hdll);
    31 
    32          }
    33 
    34 }

     后记:
             在VS2015中,NuGet程序包里有自动编译工具UnmanagedExports,设置目标平台为X86或X64,编译时IDE可以很方便的完成以上麻烦过程,不过在中文的VS2015里,程序总是编译不成功。只有自己写一个重编译工具,难度不高。
    图片 

  • 相关阅读:
    SpringMvc的执行机制和环境搭建
    Flexbox,更优雅的布局
    Laravel框架 mysql 数据库 —— 基本使用
    在 Windows 上安装 Laravel 5.x
    javascript 中的借鸡生蛋
    由斐波那契数列所引发的性能优化
    成为一名优秀的Web前端开发者
    H5之contenteditable
    ionic 集锦
    vm10虚拟机安装Mac OS X10.10教程[转]
  • 原文地址:https://www.cnblogs.com/eshell/p/5652853.html
Copyright © 2011-2022 走看看