在非托管环境下使用托管环境下的程序集(转)

时间:2021-06-15 03:15:38
 

在非托管环境下使用托管环境下的程序集(转)

转自:http://www.wwit.cn/www/down/Article.Asp?id=790

2


        自.Net问世以后,我们习惯的VC++,VB编程模式有了很大的变换,托管与非托管的概念也不断映入程序员们的眼帘,可以说.NET正逐步成为编程的主流语言和平台之一。今天不与大家讨论谁主沉浮,也不发表慷慨激扬的陈词,到底这种编程模式(
或者说是方式)好与否,由所有的程序员们在实践中去探讨证实吧!今天学习中遇到了托管与非托管环境下程序集的相互调用问题,觉得应该和大家分享一下,无论多么的简单,我只是希望在开发模式日新月异的时代,大家一定要抓住事物的变化特征。下面和大家分享一下!
        微软的.NET环境允许非托管的客户端通过微软.NET环境生成的封装类,透明的调用.NET的程序集(Assembly)。可被调用的COM封装类其实 是托管环境下的程序集的一个代理。他是由程序集里面包含的元数据生成的。原数据主要是用来描述程序集的数据比如类的声明、方法和版本信息等(类似于COM tlb文件)。所以我们可以通过封装类像使用COM组件一样轻松的调用托管环境下的程序集。

      COM
的客户端不能直接使用.NET的程序集。当调用动作发生的时候.NET的公共语言运行时给托管对象生成一个代理类。这个代理类的主要最作用是用来在托管代码和非托管代码之间调度。这和COMMarshal类似。
封装类保留了传统COM对象的引用计数风格。当引用计数为零时封装类自动释放对托管程序集的引用。当托管程序集被释放后也会被.NET的垃圾收集器标定为可收集对象。
       Type Library Exporter (Tlbexp.exe )
.NET环境提供的一个命令行工具这个工具可以为.NET托管环境下的类导出类型库(*.tlb文件)。Tlbexp.exe是根据托管环境的程序集 里面得元数据创建的tlb文件。非托管代码的应用程序使用这个tlb文件绑定.NET环境下的程序集。由于一个.NET的程序集可能还引用了其它的程序集 所以Tlbexp.exe可能产生一个或多个tlb文件。Tlbexp.exe文件只能生成tlb文件,但是并不为其注册。若想注册请使用 regasm.exe工具,这一是一个基于命令行的工具。
       Tlbexp.exe
工具把每个具有公共属性的类变成类型库的coclasscoclass的名字和程序集里类的名字保持一致。所有被显示实现的接口都被输出到类型库。实现接口的类所包含的方法和属性就不会被输出到类型库了。
       
当托管环境的程序集被Tlbexp.exe导出后所有的托管环境的接口和接口的方法和属性就被转换成COM的接口了。在缺省条件下COM组件支持双接口,您可以使用ClassInterfaceAttribute设定接口的属性。
举个例子:
public interface IHello
{
void SayHello();
}
public class Imp_Hello : IHello
{
     public void ()
   {
       System.Console.WriteLine(“Hello World”);
   }
}
Tlbexp.exe
工具就会生成以下的IDL(接口定义语言)
  [uuid(xxxxxxxxxxxxxxxx),dual,odl,oleautomation]
  interface IHello :Idispatch
  {
     HRESULT SayHello();
  }
  [uuid(xxxxxxxxxxxxxxx)]
coclass Imp_Hello  ;
{
  interface Ihello; 
}
请您注意:因为我们要导出接口和实现类,所以在上面的那段C#代码里面使用了public关键字修饰了接口和实现类。否则即使生成了tlb文件,里面也不会包含关于接口和实现类的描述。
在您调用非托管环境下的程序集之前要先把程序集注册到系统注册表。.NET环境提供了一个工具叫Regasm.exe,用来完成注册工作。
该注册工具在注册表里添加了以下项目:
  
一个是.NET托管环境的类的标识符CLSID添加在HKEY_CLASSES_ROOT\CLSID

另一个在HKEY_CLASSES_ROOT\CLSID\<class I D>下,这个表项有两个子项,
一个是ImplementedCategories通常放置类的ProgID另一个是InprocServer32用来指定.DLL的名字。
COM 客户端企图装载一个托管环境程序集的类时,.NET运行环境从系统注册表的里面读取程序集的数据传送给程序集解析器。然后解析器根据名字和版本号等基本信 息定位程序集。这个程序集只有被强命名(strong name),或是被放置在应用程序的根目录或者子目录时才能被程序集解析器正确定位。请注意:当您没有使用强命名时,清在注册时加上/codebase 参数。

通过Visual Basic 6.0使用.NET程序集的过程:
1.  
Visual Basic 6.0Project菜单,点击References
弹出References对话框
拉动滚动条找到要引用的条目点OK
创建一个.NET环境下程序集类的对象,如下:
     Dim Server As xxxxx
使用对象的方法

Visual C++6.0下使用就更为简单直接导入tlb文件即可如下:
#import "xxxxxx.tlb"  
请注意,在import 后面要加上named_guids属性,否则接口的GUID将不会被定义到工程里。