C# 代码调用 C++/CLI class 方法 - 新实例仍然具有旧实例值

C# code calling C++/CLI class method - new instance still has old instance values

我是同时使用 C# 和 C++/CLI 代码的新手。在我的 C# 代码中,我正在创建 class FooClass 和 运行 方法 FooClass:ParseCmdArgs 的新实例,它接受 System::String,转换为 std::string,然后推送到向量 "bars" 变量。然后我在 ParseCmdArgs 函数的末尾打印出 "bars" 内容。但是我得到了如下所述的一些意外输出。

C# 代码 - WPF 应用程序

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    CLRClass.FooClass foo = new CLRClass.FooClass();

    List<string> args = new List<string>();
    args.Add("1st Run - 1");
    args.Add("1st Run - 2");
    args.Add("1st Run - 3");
    args.Add("1st Run - 4");
    args.Add("1st Run - 5");

    foo.ParseCmdArgs(args.Count, args.ToArray());

    args.Clear();
    args.Add("2nd Run - 1");
    args.Add("2nd Run - 2");
    args.Add("2nd Run - 3");
    args.Add("2nd Run - 4");
    args.Add("2nd Run - 5");

    foo = new CLRClass.FooClass();
    foo.ParseCmdArgs(args.Count, args.ToArray());
}

CLRClass.h

#pragma once
#include <string>
#include <iostream>
#include <msclr\marshal_cppstd.h>

using namespace System;

namespace CLRClass {

  public ref class FooClass
  {
  public:
    void ParseCmdArgs(int, array<System::String^>^);
  };
}

CLRClass.cpp

#include "stdafx.h"

#include "CLRClass.h"

using namespace CLRClass;
using namespace std;

vector<string> bars;

void FooClass::ParseCmdArgs(int argc, array<System::String^> ^argvManaged) {
  string *argv;
  argv = new string[argc];

  for (int j = 0; j < argc; j++) {
    msclr::interop::marshal_context context;
    std::string standardString = context.marshal_as<std::string>(argvManaged[j]);

    argv[j] = standardString;

    bars.push_back(argv[j]);
  }

  cout << "print bars" << endl;
  cout << "-----------" << endl;

  for (int i = 0; i < bars.size(); i++) {
    cout << bars[i] << endl;
  }
}

输出为:

print bars
-----------
1st Run - 1
1st Run - 2
1st Run - 3
1st Run - 4
1st Run - 5
print bars
-----------
1st Run - 1
1st Run - 2
1st Run - 3
1st Run - 4
1st Run - 5
2nd Run - 1
2nd Run - 2
2nd Run - 3
2nd Run - 4
2nd Run - 5

如果你能在这里帮助我,我有几个问题:

1)没想到分配给"foo"的FooClass的第一个实例仍然保留"bars"变量的内容(在C++/CLI代码中)。正如我们从输出中看到的,在将 FooClass 的新实例分配给 "foo" 之后,“第一个 运行” 中的旧内容存储在 "new" FooClass 实例的 "bars" 多变的。 1a) 谁能明白为什么会这样? 1b) 我需要为 FooClass 设置析构函数吗?

2) 我用一个 FooClass 实例调用 ParseCmdArgs() 函数的最佳方法是什么?我想创建 FooClass 的新实例并不理想(无论如何都不起作用,请参见 1)。每次 ParseCmdArgs 完成时我都需要做一个 bars.clear() 吗??

3) 我将 System::String 编组/转换为 std::string 的方式是否正确?

4) 例如在我当前调用非托管 C++/CLI class 和使用封送处理的 C# 托管代码实现中是否存在内存泄漏问题?

预先感谢您的帮助,如果您需要进一步的详细信息或说明,请告诉我。

此致

您需要使 vector<string> bars; 成为函数的局部变量。或者至少是 class.

的实例字段

现在它是一个全局变量,只要您将 DLL 加载到您的 AppDomain 中(简单地说,在您的程序的整个持续时间内),它就会保持它的值。

这与 CLR 或托管代码无关。如果您从 C++ 可执行文件调用 C++ 代码,也会发生同样的情况。