您的位置:首页 > 编程语言 > C语言/C++

Win32C++调用C#(一):开篇

2016-07-08 11:36 453 查看
Win32C++是非托管的,C#是托管的,不管出于什么目的,有时候需要在非托管的C++里调用现存的C#类库。我经常使用的方法是修改C# il 代码,然后重新编译il以供C++调用。
有一段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里,程序总是编译不成功。只有自己写一个重编译工具,难度不高。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: