65.9K
CodeProject 正在变化。 阅读更多。
Home

从本机代码中使用 .NET 集合

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.60/5 (5投票s)

2008年5月29日

CPOL

2分钟阅读

viewsIcon

28150

downloadIcon

367

一个简短的示例,说明如何从本机 C++/ATL 访问托管的字符串 ArrayList

引言

随着项目迁移到 .NET Framework,通常需要将新开发的基于 .NET 的功能集成到现有但尚未迁移的旧版 COM 应用程序中。 理想情况下,在 .NET Framework 上开发的代码应利用该框架提供的丰富的类库。 这会给希望使用托管代码的 COM 客户端带来一些问题,因为 COM 和 .NET 具有不同的对象模型、内存模型和运行时要求。

幸运的是,许多 .NET Framework 类通过 *mscorlib.tlb* 向 COM 客户端公开。 快速查看 OleView 中的 *mscorlib.tlb* 可以发现基本框架中有多少是 COM 可见的

DotNetCollectionsFromNativeCodeDemo_OleView.GIF

还有许多类对 COM 对象可见。 事实上,API 文档中标记为 ComVisible(true) 的每个类都可以从 COM 客户端轻松访问。

Using the Code

此示例演示如何从本机 C++ 使用 System.Collections.ArrayList。 C++ 客户端使用 ATL。

托管类方法 Library.GetBooks() 返回一个 ArrayList。 单个 string 已在 Library() 构造函数中添加到此列表。 以下代码段打印列表中项目数的 count(在此示例中,只有一个)

ILibraryPtr ptrLibrary(__uuidof(Library));

IUnknown *ptrUnkBooks = NULL;

// ManagedCSharpDemoLibrary::_ArrayList is a stub struct
// created by InteropServices.  Since everything in COM
// derives from IUnknown, it's safe to cast from an IUnknown *
ptrLibrary->GetBooks((ManagedCSharpDemoLibrary::_ArrayList **)&ptrUnkBooks);

// ICollection is defined in mscorlib.tlb.  It corresponds
// to System.Collections.ICollection

ICollection *ptrCol = NULL;
ptrUnkBooks->QueryInterface(__uuidof(ICollection), (void **)&ptrCol);

long count = -1;
ptrCol->get_Count(&count);

cout << "Number of books: " << count << endl;

System.Collections.ICollection.Count 属性包含 ArrayList 中的项目数。 ICollection 只是 ArrayList 实现的众多接口之一。 这些接口中的每一个都被声明为双接口,因此它可以被早期绑定客户端(如这个 C++ 客户端)以及后期绑定客户端(例如 VBscript)访问。

要访问 ArrayList 中的各个项目,需要 IList 接口。 托管世界中的 IList.Item 属性提供对列表元素的基于零的索引访问。 可以按如下方式访问此属性

IList *ptrList = NULL;
ptrCol->QueryInterface(__uuidof(IList), (void **)&ptrList);

// ArrayLists store objects.  These are marshalled as 
// VARIANTs.  Since this list is storing strings, the
// VARIANTs are of type BSTR;

VARIANT vObj;
_variant_t vtObj; // provides a convenient way to convert to _bstr_t

for (int i=0; i < count; i++)
{
    ptrList->get_Item(i, &vObj);
        
    vtObj.Attach(vObj);

    wcout << "Found book: " << ((_bstr_t)vtObj) << endl;
}

ptrCol->Release();

此示例打印列表中的每个元素。 它可以很容易地适应不是 string 的列表。 VT_* VARIANT 宏可用于确定列表中 VARIANT 的类型。

关注点

COM C++ 编译器扩展可以大大简化 C++ 中的 COM 编程。 属性编程还提供了另一种从 C++ 轻松创建和使用 COM 类型的方法,但是仍然存在很多使用早于属性编程的 VC++ 版本的遗留项目。

历史

  • 2008 年 5 月 29 日:提交的第一个版本
© . All rights reserved.