使用C ++ / CLI包装非托管C ++类库 - 问题2 - 集合

时间:2011-01-27 17:36:19

标签: .net visual-c++ collections c++-cli wrapper

注意:这篇文章代表我的询问问题#2。在两个问题中都会重复介绍块(所有文本,直到达到数字),因为它是回答问题可能需要的背景信息。


问题简介

我有一个非托管C ++库,它包含几个“更高级别”库之间共有和共享的类和函数。我现在需要提供对C#/ .Net应用程序的公共库的访问。为此,我将使用C ++ / CLI包装类包装公共库。

公共库中包含的类可以是包含嵌套类定义和成员变量的复杂类,这些变量是其他类对象的集合。集合变量是用于管理集合的自定义列表类的typedef的实例。公共库还包括表示使用FLEX / BISON创建的自定义脚本文件语法的已解析结构的类。公共库和“更高级别”库都是以允许跨平台(Linux和GCC)编译和使用的方式编写的。我所做的任何改变都必须允许这样做。

C ++ / CLI包装器类首先只需要读取功能。但随着项目的进展,我最终还需要能够创建和修改对象。

我了解C ++ / CLI并为其他非托管C / C ++项目创建了几个包装器,并为这个公共库提供了抽象功能。所以我已经掌握了基础知识(以及一些高级知识)。

我有两个与执行此任务有关的问题,因为他们可以产生他们自己的讨论和解决方案,我将我的问题分成不同的帖子。我会在每篇文章中包含其他问题的链接。


实际问题

  1. Wrapping an Unmanaged C++ Class Library with C++/CLI - Question 1 - Project/Code Organization

  2. 如何在非托管类中有效地包装/处理集合变量?

    • 集合对象是自定义模板列表类(CObjectList<T>)的typedef,用于处理对象指针集合的管理。集合类提供所有基本集合功能以及指针管理和解构时对象的清理/释放。因此,对于CWidget,代码中会有typedef CObjectList<CWidget> CWidgetList;

    • 代码和集合类模板参数中使用的大多数类都是类本身。但在某些情况下,该集合属于基类。这发生在自定义脚本FLEX / BISON解析器的已解析结构中。例如,有一个CCommand类,所有其他可用命令都继承自该类。因此会有CSetCommandCPrintCommandCIfCommand等。

    • 我认为为了做到这一点,我将不得不创建我的集合包装类,它为非托管和C ++ / CLI类维护单独的列表。内部集合对象将管理非托管对象,并且必须有一个托管集合/列表对象来存储项目的包装类。

    • 有没有人有任何关于如何做到这一点的例子/建议?或者如何编写可以将非托管类和C ++ / CLI类类型作为参数的泛型类?

2 个答案:

答案 0 :(得分:2)

这是一个非常难以回答的问题,但我建议你有一个编组/转换层,可以从托管集合转换为非托管集合。保持你的库完全一样,只需转换参数和返回。

这就是我要做的事情

  1. 收藏品不是巨型的
  2. 他们不是经常来回传递。
  3. 您经常在客户端代码中获取该集合,然后在管理的土地上完成一系列调用。
  4. 出于这些原因

    1. 它将API分层,使其更简单
    2. 越过非托管/管理边界可能是瓶颈,应该最小化
    3. 这将是我的默认方法,除非我真的需要访问数据结构中lib的功能(它不仅仅是有组织的数据 - 而是数据和行为)

答案 1 :(得分:2)

Lou has an excellent suggestion并且我同意他关于这种方法何时良好的条件。

如果集合非常大,或者经常来回传递,那么最好实现.NET可枚举接口但不使用.NET集合。基本上,你有一个拥有本机STL集合的集合包装器,以及一个拥有本机STL迭代器的迭代器包装器。集合包装器将实现IEnumerable接口,GetEnumerator将创建迭代器包装器的实例,迭代器包装器将实现IEnumerator接口。

你想让自己成为一个帮助托管类(可能是一个值类),它将指针包装到本机集合并引用计数,如boost::shared_ptr。使用堆栈语义表示法确保在托管集合包装器或迭代器包装器处理完毕后自动完成引用计数。