我爱Aspx >> VC.Net >> C++/CLI中有效使用非托管并列缓存Visual Studio安装程序会把Visual Studio的共享库放在一个称为"并列缓存(side-by-side cache)"的地方,那怎样才能有效地利用它呢?
在文章开头,先看一个示例。在命令行中,创建一个C++源文件,输入例1中的代码。(虽然此处使用的是C++/CLI语法,但不管你是用C++/CLI、托管C++、或本地C++,都不影响要讲解的主题。)
例1:lib.cpp
| using namespace System;public ref class Test{ public: void CallMe() { Console::WriteLine("called me"); }}; |
将其编译为一个托管库程序集:
| cl /clr /LD lib.cpp |
在此要多留意,我们是使用了混合模式(/clr)来编译此代码,当然了,如果适当修改,也能以旧式托管C++语法(/clr:oldsyntax)来编译。
下一步,创建一个调用此库的C#程序(例2),当然也可以使用Visual Basic.NET,不过C#更好一点。再与库一起编译:
例2:
| using System;class App{ static void Main() { Test test = new Test(); test.CallMe(); }}csc app.cs /r:lib.dll |
运行此程序,会抛出一个异常:
| Unhandled Exception: System.IO.FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)at App.Main() |
怎么会这样呢?打开程序所在的目录,库也在那啊。HRESULT的高位字为0x8007,其代表FACILITY_WIN32,也就是说,这是一个Win32错误;低位字以十进制表示为126,在winerror.h中列明其代表ERROR_MOD_NOT_FOUND。如果LoadLibrary不能查找到某个模块,才会返回这个错误结果,因此,现在非常清楚了,这个错误表示不能查找到一个非托管的DLL。
为找出库所使用的模块列表,可在ILDASM中加载它,并查看MANIFEST。如果库是通过平台调用加载DLL的,那这些DLL会作为.module条目列出,然而,对这个库来说,你将会发现,它只用到了托管程序集mscorlib与Microsoft.VisualC,两者都在.NET全局程序集缓存(GAC)中。另有一种可能性,在程序集中,还存在着非托管代码,由它调用了非托管库(例如,那些使用托管C++ It Just Works的代码)。
为调查清楚,从ILDASM的View菜单中选项Headers,这将会列出库中的PE文件头。向下滚动直至找到导入表(IAT),会得到一份所有从非托管库引入的方法列表。因为库是以混合模式编译的,因此库用到了C运行时库(CRT),从导入表中也确认了这点--它列出了msvcr80.dll及msvcm80.dll,前者是CRT的DLL多线程版本,后者是一个包含了一些CRT托管版本的混合模式库。这下非常清楚了,错误产生的原因是Windows找不到这两个库、或其一。
【我对这篇文章有话说?】
缓冲区溢出还是问题吗?C++/CLI安..[03-16]
实例解析C++/CLI中的继承与枚举[03-16]
实例解析C++/CLI中的接口与泛型[03-16]
缓冲区溢出还是问题吗?C++/CLI安..[03-16]
Visual Basic.NET中的操作符应用..[03-16]
用WPF构建强大的用户体验[03-16]
用WPF构建强大的用户体验[03-16]
为.NET程序批上WPF的绚丽外衣[03-16]
三层Web体系结构里的两种数据绑定..[03-16]
微软软件开发技术二十年回顾[03-16]