【问题标题】:Converting std::vector<>::iterator to .NET interface in C++/CLI在 C++/CLI 中将 std::vector<>::iterator 转换为 .NET 接口
【发布时间】:2010-09-10 05:54:36
【问题描述】:

我正在包装一个原生 C++ 类,它有以下方法:

class Native
{
    public:
    class Local
    {
        std::string m_Str;
        int m_Int;
    };

    typedef std::vector<Local> LocalVec;
    typedef LocalVec::iterator LocalIter;

    LocalIter BeginLocals();
    LocalIter EndLocals();

    private:
        LocalVec m_Locals;
};

1) 表示这种接口的“.NET 方式”是什么?返回数组的单个方法? array 泛型是否有迭代器,以便我可以实现 BeginLocals() 和 EndLocals()?

2) Local 是否应该在 .NET 包装器中声明为 值结构

我真的很想用 .NET 风格来表示包装类,但我对托管世界非常陌生 - 这种类型的信息让谷歌感到沮丧......

【问题讨论】:

    标签: .net arrays vector c++-cli marshalling


    【解决方案1】:

    迭代器不能完全转换为“.net 方式”,但它们大致被 IEnumerable 和 IEnumerator 取代。

    而不是

      vector<int> a_vector;
      vector<int>::iterator a_iterator;
      for(int i= 0; i < 100; i++)
      {
        a_vector.push_back(i);
      }
    
      int total = 0;
      a_iterator = a_vector.begin();
      while( a_iterator != a_vector.end() ) {
        total += *a_iterator;
        a_iterator++;
      }
    

    你会看到(在 c# 中)

    List<int> a_list = new List<int>();
    for(int i=0; i < 100; i++)
    {
      a_list.Add(i);
    }
    int total = 0;
    foreach( int item in a_list)
    {
      total += item;
    }
    

    或者更明确地(不将 IEnumerator 隐藏在 foreach 语法糖后面):

    List<int> a_list = new List<int>();
    for (int i = 0; i < 100; i++)
    {
        a_list.Add(i);
    }
    int total = 0;
    IEnumerator<int> a_enumerator = a_list.GetEnumerator();
    while (a_enumerator.MoveNext())
    {
        total += a_enumerator.Current;
    }
    

    如您所见,foreach 只是为您隐藏了 .net 枚举器。

    所以说真的,“.net 方式”只是允许人们为自己创建 List 项目。如果您确实想控制迭代或使集合更加自定义,请让您的集合也实现 IEnumerable 和/或 ICollection 接口。

    几乎可以直接翻译成 c#:

    public class Native
    {
      public class Local
      { 
         public string m_str;
         public int m_int;
      }
    
      private List<Local> m_Locals = new List<Local>();
    
      public List<Local> Locals
      {
        get{ return m_Locals;}
      }
    }
    

    那么用户就可以

    foreach( Local item in someNative.Locals)  
    {
     ... 
    }
    

    【讨论】:

      【解决方案2】:

      @Phillip - 谢谢,您的回答确实让我朝着正确的方向开始。

      在看到您的代码并在 Nish 的书 C++/CLI in Action 中进行了更多阅读后,我认为使用索引属性将 const 跟踪句柄返回到托管堆上的 Local 实例可能是最好的方法。我最终实现了类似于以下内容:

      public ref class Managed
      {
          public:
          ref class Local
          {
              String^ m_Str;
              int m_Int;
          };
      
          property const Local^ Locals[int]
          {
              const Local^ get(int Index)
              {
                  // error checking here...
                  return m_Locals[Index];
              }
          };
      
          private:
              List<Local^> m_Locals;
      };
      

      【讨论】:

      • 这是一个好方法,但您可能还需要确保至少公开一个 Count 属性:)。另请注意,如果不公开列表或实现 IEnumerable,则 .net 3.5 中的 LINQ 扩展将无法使用该类
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多