问题描述
我正在用 C# 编写一个 GUI 工具来解析和显示另一个用 C 编写的程序的数据输出.为了解析数据,我需要知道在许多 C 头文件中指定的数据结构.因此,我需要将这些 C 头文件合并到我的 C# 项目中.我的问题是:
I am writing a GUI tool in C# to parse and display the data output of another program written in C. In order to parse the data I need to know the data structures which are specified in a number of C header files. Thus I need to incorporate those C header files into my C# project. My questions are:
1) 经过一些研究,我得出结论,最好的方法是在我的解决方案中创建一个新的 C++/CLI 项目,将 C 头文件导入这个新项目,编写一些充当瘦包装器的 C++/CLI 类对于 C 头文件中定义的数据结构,然后从 C# 代码中引用 C++/CLI 包装类.这是最好的方法,还是有更好的方法?
1) After some research I came to conclude that the best way is to create a new C++/CLI project in my solution, import the C header files into this new project, write some C++/CLI classes that act as thin wrappers for the data structures defined in the C header files, then reference the C++/CLI wrapper classes from the C# code. Is this the best approach, or is there a better way?
2) 我遇到了参考问题.这是我的简化代码来说明问题:
2) I ran into a reference problem. Here's my simplified code to illustrate the problem:
C++/CLI 项目中的原始 C 头文件
Original C header in C++/CLI project
#define ABC 0x12345
C++/CLI 项目中的包装类
Wrapper class in C++/CLI project
#include "my_c_header.h"
namespace C_Wrappers {
public ref class MyWrapper {
public:
property unsigned int C_ABC {
unsigned int get() { return ABC; }
}
}
}
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());
}
}
}
在 C# 项目中,我添加了对 C++/CLI 项目的引用(使用右键单击 > 添加引用).在构建期间,我在 C# 项目中遇到错误:找不到类型或命名空间 'C_Wrappers'(您是否缺少 using 指令或程序集引用?)."
In the C# project I added a reference to the C++/CLI project (using right click > Add Reference). During build I got an error in the C# project: "The type or namespace 'C_Wrappers' could not be found (are you missing a using directive or an assembly reference?)."
我以为我做了我应该做的一切.我应该怎么做才能修复这个错误?
I thought I did everything I was supposed to. What should I do to fix this error?
推荐答案
在我自己的解决方案中,我有 4 个项目:
In my own solution, I had 4 projects:
- C++ 项目和测试代码
- C++ DLL 项目,仅使用动态链接从第一个项目源中编译 DLL
- 包装器项目,它只是一个使用 C++/CLI 的适配器,它包装了原始 C++
- C# WPF 项目,这是我的图形界面.
- the C++ project and the test code
- the C++ DLL project which only compiles a DLL out of the first project source using dynamic links
- the wrapper project which is only an adapter using C++/CLI, which wraps around the raw C++
- the C# WPF project which was my graphical interface.
这是我对上面提供的链接的翻译.
Here's my translation of the provided link above.
将您的 C++ 代码转换为 DLL 库.
Make your C++ code into a DLL lib.
- 在 Visual Studio 中,转到 File > New > Project,从 Visual C++ 选项卡中选择 Win32 project.
- 为项目和解决方案选择一个名称,解决方案将包含所有项目.
- 在 Win32 应用程序助手中,点击下一步,勾选DLL框,然后点击Empty project,然后点击Finish强>.
- Inside Visual Studio, go to File > New > Project, Select Win32 project from the Visual C++ tab.
- Choose a name for both the project and the Solution, the solution will have all the projects inside.
- Inside the assistant for Win32 Application, click next, check the DLL box, then Empty project then click Finish.
这是我的 dll 的 C++ 头文件(减去很多东西).
This is my C++ header for the dll (minus lot of stuff).
令牌.h
#pragma once
#define DLLEXP __declspec( dllexport )
DLLEXP void pop_back(std::string& str);
DLLEXP std::string testReturnString();
DLLEXP int getRandomNumber();
CPP 内部没有什么可改变的.
There's nothing to change inside the CPP.
构建项目,您应该有一个 DLL 和一个 LIB 文件以包含在 C# 项目调试目录中.
Build the project, you should have a DLL and a LIB file to include in the C# project debug dir.
此项目用作上一个项目的本机代码与 GUI 的托管代码之间的接口.
This project serves as an interface between the native code from the previous project, and managed code of the GUI.
- 向解决方案添加一个新项目(Visual C++ 中的类库)(在本例中称为Wrapper")
- 使用附加的包含目录添加本机项目的路径
- 将本机项目添加为新项目的参考(右键单击 > 参考... > 添加新链接)
- 在Properties > Linker > Input中,将本机dll的名称放在延迟加载DLL(本例中为Computations.dll)字段中
- Add a new project (class library in Visual C++) (called "Wrapper" in this example) to the solution
- Add the path to the native project with the additional Include directories
- Add the native project as a reference for the new project (right click > References... > Add New Link)
- In Properties > Linker > Input, put the name of the native dll in the delayed loading of DLLs (Computations.dll in this example) field
C++/CLI 代码
我的包装器只是一个看起来像这样的类(减去我自己的代码).
The C++/CLI code
My wrapper is only a class which looks something like this (minus my own code).
包装器.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);
};
}
CPP 中没有什么特别之处,只是您必须包含 #include "stdafx.h"
.
Nothing special inside the CPP except that you have to include #include "stdafx.h"
.
它还应该构建到一个 DLL 中,您将把它包含在 C# 调试目录中.
It should also builds into a DLL which you will include inside the C# debug dir.
只是我在 SO 某处找到的一个有用功能,但不记得您可能需要的位置.它将 C++/CLI 字符串句柄转换为 C++ 标准字符串.
Just a useful function I found somewhere on SO but don't remember where that you might need. It convert C++/CLI String handle into a C++ standard string.
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;
}
C# 项目
向解决方案添加一个新项目(C# Windows Form 或 WPF 或任何你想要的!)并将其设置为启动项目(right-点击 > 设置为启动项目).
The C# project
Add to the solution a new project (C # Windows Form or WPF or whatever you want!) and set it as the startup project (right-click > set as startup project).
- 添加 C++/CLI 项目作为新项目的参考
- 以源代码形式添加指令
using Wrapper;
像这样使用它:
/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();
2016/05/06 更新
阿什温 花时间制作了一个 示例项目 和一个 博文教程可能会有所帮助.
Ashwin took the time to make a sample project and a blog post tutorial which may help further.
这篇关于如何从 C# 访问 C++/CLI 中的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!