最直接的实现托管与非托管编程的方法就是使用C++/CLI
介绍项目存档一直是企业的采用的做法,而是事实证明他们也是对的!对于一个程序员,这是几千men-days的工作量。为什么不开发一小段代码去重新利用那段代码,项目。
现在提供了一个渐渐的转向C#的新技术: 使用托管与非托管的混合编程。这是一个可行的方案在top-down issue(from UI to low-level layers)or bottom-up(from low-level to UI)案例。
本文目的就是通过两个简单的例子来说明怎么一起使用这两种技术:
* 在非托管中调用托管代码。
* 在托管中调用非托管代码。
这个例子主要展示了在非托管代码(C++)中调用使用托管(C#)代码实现类,通过托管代码实现"mixed code"DLL 来导出API。 单一的非托管代码
以下是一个控制台程序
#include "stdafx.h" #include <iostream> using namespace std; #ifdef _UNICODE #define cout wcout #define cint wcin #endif int _tmain(int argc, TCHAR* argv[]) { UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv); SYSTEMTIME st = {0}; const TCHAR* pszName = _T("John SMITH"); st.wYear = 1975; st.wMonth = 8; st.wDay = 15; CPerson person(pszName, &st); cout << pszName << _T(" born ") << person.get_BirthDateStr().c_str() << _T(" age is ") << person.get_Age() << _T(" years old today.") << endl; cout << _T("Press ENTER to terminate..."); cin.get(); #ifdef _DEBUG _CrtDumpMemoryLeaks(); #endif return 0; }这段代码没有什么特殊的,这只是个再普通不过的非托管代码。
单一的托管代码这是个典型的使用C#实现的装配器
using System; namespace AdR.Samples.NativeCallingCLR.ClrAssembly { public class Person { private string _name; private DateTime _birthDate; public Person(string name, DateTime birthDate) { this._name = name; this._birthDate = birthDate; } public uint Age { get { DateTime now = DateTime.Now; int age = now.Year - this._birthDate.Year; if ((this._birthDate.Month > now.Month) || ((this._birthDate.Month == now.Month) && (this._birthDate.Day > now.Day))) { --age; } return (uint)age; } } public string BirthDateStr { get { return this._birthDate.ToShortDateString(); } } public DateTime BirthDate { get { return this._birthDate; } } } }正如所见,这这是个单一的CLR
托管与非托管混合编程部分这部分是最重要,也是最难的。VisualStudio环境提供了一些头文件来帮助开发者链接这些关键词。
#include <vcclr.h>但是,并非就到这儿就结束了。我们还需要小心涉及的一些陷阱,尤其是是CLR(托管代码)和native(非托管代码)一些关键词之间数据的传递。
以下是个类的头文件输出一个托管的部分