我是一起使用C#和C ++ / CLI代码的新手。在我的C#代码中,我正在创建一个类FooClass的新实例并运行一个方法FooClass:ParseCmdArgs,它接受一个System :: String,转换为一个std :: string,然后推送到一个向量"杆"变量。然后我打印出" bar" ParseCmdArgs函数末尾的内容。但是我得到了下面描述的一些意想不到的输出。
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)我没想到FooClass的第一个实例分配给&#34; foo&#34;仍然保留&#34;酒吧&#34;的内容变量(在C ++ / CLI代码中)。正如我们从输出中看到的那样,在将一个新的FooClass实例分配给&#34; foo&#34;之后,来自&#34; 1st Run&#34;的旧内容。存储在&#34; new&#34; FooClass实例&#34;&#34;&#34;变量。 1a)有人能看出为什么会这样吗? 1b)我是否需要为FooClass设置析构函数?
2)用一个FooClass实例调用ParseCmdArgs()函数的最佳方法是什么?我想创建一个新的FooClass实例并不理想(不管怎么说都没有,见1)。每次ParseCmdArgs完成时我是否需要执行bars.clear()?
3)我编组/将System :: String转换为std :: string的方式是正确的吗?
4)例如在我当前实现的调用非托管C ++ / CLI类的C#托管代码以及编组的使用中是否存在内存泄漏问题?
感谢您的帮助,如果您需要进一步的详细信息或说明,请与我们联系。
最好的问候
答案 0 :(得分:1)
您需要将vector<string> bars;
作为函数的局部变量。或者至少是你班级的实例领域。
现在它是一个全局变量,只要您将DLL加载到AppDomain中(只需在程序的整个持续时间内放置),它就会保持其值。
这与CLR或托管代码无关。如果从C ++可执行文件调用C ++代码,也会发生同样的情况。