【本文章发布于CSDN,未经个人同意不得转载】
因为操作太多了,纯文本描述实在是不方便,直接来个图文说明
①、【一个平淡无奇的C++空项目】
②、【设置该C++项目的项目属性】 “符合模式”这个东西我也不知道是干啥的,但我也不怎么感兴趣,翻车的时候再来看看好了
③、【写一个C++的托管类(CLI),调用之前写的C++类,然后生成DLL文件】 简单说明下这个CLI的语法: ①、托管类要用ref声明,并且添加public声明用于外部项目的使用; ②、托管类里头的公有部分的复杂数据类型统统都是C#的数据类型例如System::Collections::Generic::List啥的(当然也可以是自己写的其他的托管类),并且那些数据类型都必须使用引用^; ③、在cpp文件里生成个C#的数据对象是使用gcnew的而不是new的; ④、C++的类/数据结构是不能出现在公有部分中的(你写了就直接给你报错),但可以出现在私有部分中。 更多关于CLI语法上的细节请自行搜索查看其它人的文章博客。
④、【添加一个CS项目去调用这个DLL文件】
【其他】 那时我可是被那“CLI 字典 数组 列表”啥的给整恶心了啊,搜需要的数据类型但啥也搜不到(姿势不对?)。然后不知道怎么的我打开了“对象浏览器”于是走进新大陆。(其实CLI的数据类型说白了就是C#的数据类型只是当时蠢没有意识到
不想一个个文件复制黏贴的话可以直接在GitHub里下载项目,传送门:【GitHub/CLI_Demo】
【Record.h】
#pragma once
#ifndef RECORD_H
#define RECORD_H
#include<vector>
#include<map>
#include<string>
class Record {
private:
std::map<char,std::vector<std::string>>mapping;
public:
void AddString(std::string str);
std::vector<std::string>GetString(char ch);
std::map<char, std::vector<std::string>>GetMapping();
};
#endif
【Record.cpp】
#include"Record.h"
void Record::AddString(std::string str){
mapping[str[0]].push_back(str);
}
std::vector<std::string> Record::GetString(char ch){
if (mapping.find(ch) == mapping.end())
return std::vector<std::string>();
return mapping[ch];
}
std::map<char, std::vector<std::string>> Record::GetMapping(){
return mapping;
}
【Main.cpp】
#include"Record.h"
#include<iostream>
int main() {
Record rec;
rec.AddString("123");
rec.AddString("134");
rec.AddString("234");
auto mapping=rec.GetMapping();
for (auto p = mapping.begin(); p != mapping.end(); ++p) {
std::cout << "[" << p->first << "]\n";
for (auto q = p->second.begin(); q != p->second.end(); ++q) {
std::cout << *q << "\n";
}
std::cout << std::endl;
}
return 0;
}
【Controller.h】
#pragma once
#ifndef CONTROLLER_H
#define CONTROLLER_H
using namespace System::Collections::Generic;
class Record;
public ref class Controller {
private:
Record* ptr;
public:
Controller();
~Controller();
void XJ_AddString(System::String^ str);
List<System::String^>^ XJ_GetString(System::Char^ ch);
Dictionary<System::Char,List<System::String^>^>^XJ_GetDict();
};
#endif
【Controller.cpp】
#include "Controller.h"
#include"Record.h"
Controller::Controller(){
ptr = new Record();
}
Controller::~Controller(){
delete ptr;
}
void Controller::XJ_AddString(System::String^ str){
ptr->AddString(std::string((char*)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str)).ToPointer()));
}
List<System::String^>^ Controller::XJ_GetString(System::Char^ ch){
std::vector<std::string> rst = ptr->GetString(System::Convert::ToByte(ch));
auto data=gcnew List<System::String^>();
for (auto i = rst.begin(); i != rst.end(); ++i)
data->Add(gcnew System::String(i->data()));
return data;
}
Dictionary<System::Char, List<System::String^>^>^ Controller::XJ_GetDict(){
auto data =gcnew Dictionary<System::Char, List<System::String^>^>();
auto tmp = ptr->GetMapping();
for (auto i = tmp.begin(); i != tmp.end(); ++i) {
char key = i->first;
for (auto j = i->second.begin(); j != i->second.end(); ++j) {
char key = i->first;
std::string str = *j;
if (data->ContainsKey(key) == false)
data->Add(key, gcnew List<System::String^>());
data[System::Char(key)]->Add(gcnew System::String(str.data()));
}
}
return data;
}
【Main.cs】
using System;
using System.Collections.Generic;
public class Program {
static void Main(string[] args) {
Controller ctr = new Controller();
ctr.XJ_AddString("A");
ctr.XJ_AddString("AB");
ctr.XJ_AddString("ABC");
ctr.XJ_AddString("1");
ctr.XJ_AddString("12");
ctr.XJ_AddString("123");
char[] test = { 'A', 'B', 'C', '1', '2', '3' };
for (uint t = 0; t < test.Length; ++t) {
var rst = ctr.XJ_GetString(test[t]);
Console.WriteLine("【" + test[t] + "】");
foreach (var str in rst)
Console.WriteLine(str);
Console.WriteLine();
}
Console.Clear();
var dict = ctr.XJ_GetDict();
foreach (var x in dict) {
Console.WriteLine("【" + x.Key + "】");
foreach (var str in x.Value)
Console.WriteLine(str);
Console.WriteLine();
}
Console.ReadKey();
return;
}
}
|