Win32C++调用C#(一):开篇
2016-07-08 11:36
453 查看
Win32C++是非托管的,C#是托管的,不管出于什么目的,有时候需要在非托管的C++里调用现存的C#类库。我经常使用的方法是修改C# il 代码,然后重新编译il以供C++调用。
有一段cs代码:
编译后生成ManagedLib.dll文件,用ildasm工具打开该文件,然后保存为ManagedLib.il文件,修改以下代码:
修改后的代码:
用ilasm工具编译il文件,编译成功后.corflags 自动变成了0x00000002,同时增加了如下指令
增加.vtfixup 和.data两条指令负是为了责非托管导出。
现在,假设有x个函数,在需要导出的函数内部分别增加两条指令,其中,x对应要导出的函数个数
在C++中动态调用Add函数
把ManagedLib.dll文件拷贝到C++应用程序目录,在C++文件中增加以下代码:
后记:
在VS2015中,NuGet程序包里有自动编译工具UnmanagedExports,设置目标平台为X86或X64,编译时IDE可以很方便的完成以上麻烦过程,不过在中文的VS2015里,程序总是编译不成功。只有自己写一个重编译工具,难度不高。
有一段cs代码:
using System; namespace ManagedLib { public classExport { publics tatic int Add(int a, intb)//函数修饰符限定为public和static,这里是必须的 { return a + b; } } }
编译后生成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++文件中增加以下代码:
typedef int(_stdcall *Dllfun)(int,int);//必须设置_stdcall,否则运行时出错。 void ManagedCall() { Dllfun addfun; HINSTANCE hdll; hdll= LoadLibrary(_T("ManagedLib.dll")); if(hdll != NULL) { addfun= (Dllfun)GetProcAddress(hdll, "Add"); if(addfun != NULL) { int result = addfun(1, 2); LPTSTR szBuffer = new TCHAR[100]; _snwprintf_s(szBuffer,100, 100, L"a+b:%d",result); MessageBoxEx(NULL,szBuffer, _T("ManagedLib.dll"),0, 0); } FreeLibrary(hdll); } }
后记:
在VS2015中,NuGet程序包里有自动编译工具UnmanagedExports,设置目标平台为X86或X64,编译时IDE可以很方便的完成以上麻烦过程,不过在中文的VS2015里,程序总是编译不成功。只有自己写一个重编译工具,难度不高。
相关文章推荐
- 遇见C++ Lambda
- C++ 利用流来进行string和其他类的转换
- 抛出异常与栈展开(stack unwinding)
- c++——union、struct、enum
- VS .h 和 .cpp 切换快捷键设置
- “warning: this decimal constant is unsigned only in ISO C90”的解决办法
- c 字符串与C++string
- C++ Refactoring in Visual Studio 2015
- 从事游戏开发怎么入门
- 《设计模式》之Creational模式:Abstract Factory
- 【c++程序】this指针详解
- C++ heap 大根堆 小根堆
- c++智能指针
- Qt/C++ 加载数据库出现qt_sql_default_connection提醒
- C++volatile详解
- MFC学习笔记3_消息对话框
- C++ list的基本操作和使用
- 推理问题
- c++指针输出
- 什么时候用C而不用C++