如何从 C# 访问 C++/CLI 中的类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19163839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to access class in C++/CLI from C#?
提问by Thomas Nguyen
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:
我正在用 C# 编写一个 GUI 工具来解析和显示另一个用 C 编写的程序的数据输出。为了解析数据,我需要知道在许多 C 头文件中指定的数据结构。因此,我需要将这些 C 头文件合并到我的 C# 项目中。我的问题是:
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?
1)经过一些研究,我得出结论,最好的方法是在我的解决方案中创建一个新的 C++/CLI 项目,将 C 头文件导入到这个新项目中,编写一些 C++/CLI 类作为数据的瘦包装器C 头文件中定义的结构,然后从 C# 代码中引用 C++/CLI 包装类。这是最好的方法,还是有更好的方法?
2) I ran into a reference problem. Here's my simplified code to illustrate the problem:
2)我遇到了一个参考问题。这是我的简化代码来说明问题:
Original C header in C++/CLI project
C++/CLI 项目中的原始 C 头文件
#define ABC 0x12345
Wrapper class in C++/CLI project
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; }
}
}
}
User class in C# project
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());
}
}
}
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?)."
在 C# 项目中,我添加了对 C++/CLI 项目的引用(使用右键单击 > 添加引用)。在构建期间,我在 C# 项目中遇到错误:“找不到类型或命名空间‘C_Wrappers’(您是否缺少 using 指令或程序集引用?)。”
I thought I did everything I was supposed to. What should I do to fix this error?
我以为我做了我应该做的一切。我应该怎么做才能修复这个错误?
回答by Emile Bergeron
In my own solution, I had 4 projects:
在我自己的解决方案中,我有 4 个项目:
- the C++ projectand the test code
- the C++ DLL projectwhich only compiles a DLL out of the first project source using dynamic links
- the wrapper projectwhich is only an adapter using C++/CLI, which wraps around the raw C++
- the C# WPF projectwhich was my graphical interface.
- 在C ++项目和测试代码
- 仅使用动态链接从第一个项目源中编译 DLL的C++ DLL 项目
- 该包装项目,其是仅使用C ++ / CLI,其周围的纯粹的C包装一个适配器++
- 在C#WPF项目这是我的图形界面。
Here's my translation of the provided link above.
这是我对上面提供的链接的翻译。
The C++ DLL project
C++ DLL 项目
Make your C++ code into a DLL lib.
将您的 C++ 代码转换为 DLL 库。
- Inside Visual Studio, go to File > New > Project, Select Win32 projectfrom 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 DLLbox, then Empty projectthen click Finish.
- 在 Visual Studio 中,转到File > New > Project,从 Visual C++ 选项卡中选择Win32 项目。
- 为项目和解决方案选择一个名称,解决方案将包含所有项目。
- 在 Win32 Application 助手中,单击next,选中DLL框,然后Empty project ,然后单击Finish。
Code to add
要添加的代码
This is my C++ header for the dll (minus lot of stuff).
这是我的 dll 的 C++ 头文件(减去很多东西)。
Token.h
令牌.h
#pragma once
#define DLLEXP __declspec( dllexport )
DLLEXP void pop_back(std::string& str);
DLLEXP std::string testReturnString();
DLLEXP int getRandomNumber();
There's nothing to change inside the CPP.
CPP内部没有什么可以改变的。
Build the project, you should have a DLL and a LIB file to include in the C# project debug dir.
构建项目,您应该有一个 DLL 和一个 LIB 文件以包含在 C# 项目调试目录中。
The C++/CLI wrapper
C++/CLI 包装器
This project serves as an interface between the native code from the previous project, and managed code of the GUI.
该项目用作前一个项目的本机代码和 GUI 的托管代码之间的接口。
- 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
- 向解决方案添加一个新项目(Visual C++ 中的类库)(在本例中称为“Wrapper”)
- 使用额外的 Include 目录添加本机项目的路径
- 添加本机项目作为新项目的引用(右键单击 > 引用... > 添加新链接)
- 在Properties > Linker > Input 中,将本机 dll 的名称放在 DLLs 的延迟加载(本例中为 Computations.dll)字段中
The C++/CLI code
C++/CLI 代码
My wrapper is only a class which looks something like this (minus my own code).
我的包装器只是一个看起来像这样的类(减去我自己的代码)。
Wrapper.h
包装器.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);
};
}
Nothing special inside the CPP except that you have to include #include "stdafx.h"
.
除了必须包含#include "stdafx.h"
.
It should also builds into a DLL which you will include inside the C# debug dir.
它还应该构建到一个 DLL 中,您将包含在 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.
只是我在 SO 某处找到的一个有用功能,但不记得您可能需要的位置。它将 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;
}
The C# project
C# 项目
Add to the solution a new project (C # Windows Formor WPFor whatever you want!) and set it as the startup project (right-click > set as startup project).
向解决方案添加一个新项目(C#Windows 窗体或WPF或任何您想要的!)并将其设置为启动项目(右键单击 > 设置为启动项目)。
- Add the C++/CLI project as a reference for the new project
- Add Directive
using Wrapper;
in source code form
- 添加 C++/CLI 项目作为新项目的参考
using Wrapper;
以源代码形式添加指令
Use it like:
像这样使用它:
/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();
Update 2016/05/06
更新 2016/05/06
Ashwintook the time to make a sample projectand a blog post tutorialwhich may help further.
回答by Bartel
For me, the answer to thissimilar question solved that same error in C#.
对我来说,这个类似问题的答案解决了 C# 中的相同错误。
(i.e. I had a wrapper header file in my C++\CLI project, but forgot to include a .cpp file as well (even though it only has two lines in it: #include "stdafx.h" and #include "Wrapper.h"))
(即,我的 C++\CLI 项目中有一个包装头文件,但也忘记包含一个 .cpp 文件(即使它只有两行:#include "stdafx.h" 和 #include "Wrapper.h "))