在 C++/CLI 中将 std::vector<>::iterator 转换为 .NET 接口

发布于 2024-07-05 05:40:52 字数 607 浏览 7 评论 0 原文

我正在包装一个本机 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 方式”是什么? 返回数组的单个方法<>? 数组<>是否? generic 有迭代器,这样我就可以实现 BeginLocals() 和 EndLocals() 吗?

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

我真的很想用 .NET 风格来表示包装类,但我对托管世界非常陌生 - 并且这种类型的信息对于谷歌来说是令人沮丧的......

I am wrapping a native C++ class, which has the following methods:

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) What is the ".NET way" of representing this same kind of interface? A single method returning an array<>? Does the array<> generic have iterators, so that I could implement BeginLocals() and EndLocals()?

2) Should Local be declared as a value struct in the .NET wrapper?

I'd really like to represent the wrapped class with a .NET flavor, but I'm very new to the managed world - and this type of information is frustrating to google for...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

菊凝晚露 2024-07-12 05:40:52

迭代器并不完全可以翻译为“.net 方式”,但它们大致被 IEnumerable < 替代。 T> 和 IEnumerator < T>。

而不是

  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< T> 和/或 ICollection< T> 接口也是如此。

几乎直接翻译成 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)  
{
 ... 
}

Iterators aren't exactly translatable to "the .net way", but they are roughly replaced by IEnumerable < T > and IEnumerator < T >.

Rather than

  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++;
  }

you would see (in 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;
}

Or more explicitly (without hiding the IEnumerator behind the foreach syntax sugar):

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;
}

As you can see, foreach just hides the .net enumerator for you.

So really, the ".net way" would be to simply allow people to create List< Local > items for themselves. If you do want to control iteration or make the collection a bit more custom, have your collection implement the IEnumerable< T > and/or ICollection< T > interfaces as well.

A near direct translation to c# would be pretty much what you assumed:

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;}
  }
}

Then a user would be able to

foreach( Local item in someNative.Locals)  
{
 ... 
}
如痴如狂 2024-07-12 05:40:52

@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;
};

@Phillip - Thanks, your answer really got me started in the right direction.

After seeing your code, and doing a little more reading in Nish's book C++/CLI in Action, I think using an indexed property that returns a const tracking handle to a Local instance on the managed heap is probably the best approach. I ended up implementing something similar to the following:

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;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文