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里,程序总是编译不成功。只有自己写一个重编译工具,难度不高。
图片 

原文地址:https://www.cnblogs.com/eshell/p/5652853.html