c++ 混合的、纯的和可检验的代码

 

混合的、纯的和可检验的代码

对于.NET 程序设计来说,Visual C++ 支持创建3种类型的组件和应用程序:混合的mixed)、纯的pure)和可检验的verifiable)。通过使用 /cls 编译选项,便可得到这3种东西。

1.混合的程序集(/clr

混合程序集(用 /clr 选项编译)包含非托管机器指令和托管MSIL指令。这样就让这些程序集可以调用.NET 组件和被.NET组件斯调用,且保留了与完全非托管代码组件的兼容性。使用混合程序集,开发者可以用托管功能和非托管功能混合编写应用程序。这使得混合程序集适合于从现有的C++ 应用程序迁移到.NET平台上。用这种方式来使用C++ 混合托管和非托管代码称为互操作(Interop)。

例如,一个全部由非托管函数组成的应用程序,可以用/clr选项仅重新编译其中的某一个模块,这样该程序就可以用在 .NET平台上了。因为这个模块能够使用 .NET的特性,且仍然与该应用程序的其余部分保持兼容。通过这种办法,一个应用程序就可以逐步地、一块一块地转换到 .NET平台上。甚至于还可以在一个文件内,一个函数一个函数地采用托管和非托管编译。

注意:/clr 编译选项为编译的函数提供了模块(函数)级的控制,既可按托管方式、也可按非托管方式进行编译。非托管函数只能对本地平台进行编译,且这部分程序执行时也只由CLR传递给本地平台。当使用 /clr 时,函数默认地变成了托管代码。如果编译时没有使用 /clr 选项,编译程序就会不考虑程序是非否添加了托管或非托管的编译指示符。编译指示符应放在编译函数模块的前面,而不是放在函数体内。

当模板函数取实例时,模板定义时的编译指示符决定了它到底是托管的还是非托管的。

例子

// pragma_directives_managed_unmanaged.cpp

// compile with: /clr

#include <stdio.h>

// func1 is managed

void func1() {

   System::Console::WriteLine("In managed function.");

}

 

// #pragma unmanaged

// push managed state on to stack and set unmanaged state

#pragma managed(push, off)  // 参见注释A

 

// func2 is unmanaged

void func2() {

   printf("In unmanaged function.\n");

}

 

// #pragma managed

#pragma managed(pop)

// main is managed

int main() {

   func1();

   func2();

}

注释A:为把函数编译成托管的或非托管的,须启用函数级的编译指示功能。

#pragma managed

#pragma unmanaged

#pragma managed([push,] on | off)

#pragma managed(pop)

 

    输出:

In managed function.

In unmanaged function.

2.纯的(/clr:pure

纯程序集除包含托管函数外,还可包含本地数据类型和托管数据类型。与混合程序集相似,纯程序集可以通过P/Invoke(参见“在C++ 中使用显式PInvokeDllImport Attribute)”)与本地 DLL 互操作,但不能使用C++ 的互操作特性。此外,纯程序集不能导出可从本地函数中调用的函数,因为纯程序集中的入口点使用了__clrcall调用约定。

3.可检验的(/clr:safe

/clr:safe 编译选项可生成可检验的程序集,与用 VB C# 编写的程序集一样,它们遵从下述要求:让 CLR 保证代码不违反当前的安全设置。例如,如果安全设置禁止组件写盘,CLR就会在执行代码前决定是否某可检验组件满足这个标准。可检验组件没有 CRT(运行时间库)的支持。(纯程序集对C运行库的所有纯MSIL版本都可以使用 CRT 支持。)其优点是:

增强了安全性;

某些情况下需要使用它(如SQL组件);

● Windows 的新版本会加强对组件和程序的可检验性要求。

缺点是,不能使用C++的互操作性。可检验程序集不能包含非托管函数或本地数据类型,既使托管代码没有引用它们。

尽管使用了“安全”一词,但用 /clr:safe 编译程序时并不意味着不会产生垃圾;它只是说CLR在运行时会检查安全性设置而已。

与程序集的类型无关,从托管程序集中通过 P/Invoke 调用本地本地DLL会将被编译,但在运行时仍然可能会失败,这取决于安全性设置。

posted @ 2009-07-27 10:49  shalang  阅读(314)  评论(0编辑  收藏  举报