Tho*_*yen 12 c# dependencies c++-cli dependency-management
我正在用C#编写一个GUI工具来解析和显示用C编写的另一个程序的数据输出.为了解析数据,我需要知道在多个C头文件中指定的数据结构.因此,我需要将这些C头文件合并到我的C#项目中.我的问题是:
1)经过一些研究后我得出结论,最好的方法是在我的解决方案中创建一个新的C++/CLI项目,将C头文件导入到这个新项目中,编写一些C++/CLI类作为数据的薄包装器在C头文件中定义的结构,然后从C#代码引用C++/CLI包装器类.这是最好的方法,还是有更好的方法?
2)我遇到了参考问题.这是我的简化代码来说明问题:
C++/CLI项目中的原始C头
#define ABC 0x12345
Run Code Online (Sandbox Code Playgroud)
C++/CLI项目中的包装类
#include "my_c_header.h"
namespace C_Wrappers {
public ref class MyWrapper {
public:
property unsigned int C_ABC {
unsigned int get() { return ABC; }
}
}
}
Run Code Online (Sandbox Code Playgroud)
C#项目中的用户类
using C_Wrappers;
using System;
namespace DataViewer {
public partial class MainForm : Form {
private MyWrapper myWrapper = new MyWrapper();
public MainForm() {
Console.WriteLine(myWrapper.C_ABC.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
在C#项目中,我添加了对C++/CLI项目的引用(使用右键单击>添加引用).在构建期间,我在C#项目中遇到错误:"找不到类型或命名空间'C_Wrappers'(你是否缺少using指令或程序集引用?)."
我以为我做了我应该做的一切.我该怎么做才能解决这个错误?
Emi*_*ron 23
当我需要使用WPF将C++链接到C#时,我发现这个链接非常有用.不幸的是,它是用法语写的,所以我链接了谷歌提供的翻译版本.
在我自己的解决方案中,我有4个项目:
这是我上面提供的链接的翻译.
将您的C++代码转换为DLL库.

这是我的dll的C++标题(减去很多东西).
Token.h
#pragma once
#define DLLEXP __declspec( dllexport )
DLLEXP void pop_back(std::string& str);
DLLEXP std::string testReturnString();
DLLEXP int getRandomNumber();
Run Code Online (Sandbox Code Playgroud)
CPP内部没有任何改变.
构建项目,你应该有一个DLL和一个LIB文件包含在C#项目调试目录中.
该项目用作前一个项目的本机代码和GUI的托管代码之间的接口.
我的包装器只是一个看起来像这样的类(减去我自己的代码).
Wrapper.h
#include "Token.h" // include your C++ header
#include <string>
#include <iostream>
namespace Wrapper {
// noticed the ref?
public ref class TokenAnalyzer
{
public:
TokenAnalyzer(){
};
void Init();
// use the C++/CLI type, like String^ (handles)
System::String^ ProcessLine(int lineNbr, System::String^ line);
};
}
Run Code Online (Sandbox Code Playgroud)
CPP内部没什么特别的,除非你必须包括#include "stdafx.h".
它还应该构建一个DLL,你将包含在C#debug目录中.
只是一个有用的功能,我发现在某处,但不记得你可能需要的地方.它将C++/CLI字符串句柄转换为C++标准字符串.
std::string MarshalString (String ^ s) {
using namespace Runtime::InteropServices;
const char* chars =
(const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
std::string os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
return os;
}
Run Code Online (Sandbox Code Playgroud)
向解决方案添加一个新项目(C#Windows窗体或WPF或任何您想要的!)并将其设置为启动项目(右键单击>设置为启动项目).
using Wrapper;以源代码形式添加指令使用它像:
/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();
Run Code Online (Sandbox Code Playgroud)
更新2016/05/06
Ashwin花时间制作了一个示例项目和博客文章教程,可能会有所帮助.