如何从 C# 访问 C++/CLI 中的类?
Posted
技术标签:
【中文标题】如何从 C# 访问 C++/CLI 中的类?【英文标题】:How to access class in C++/CLI from C#? 【发布时间】:2013-10-10 10:13:07 【问题描述】:我正在用 C# 编写一个 GUI 工具来解析和显示另一个用 C 编写的程序的数据输出。为了解析数据,我需要知道在许多 C 头文件中指定的数据结构。因此,我需要将这些 C 头文件合并到我的 C# 项目中。我的问题是:
1) 经过一番研究,我得出结论,最好的方法是在我的解决方案中创建一个新的 C++/CLI 项目,将 C 头文件导入这个新项目,编写一些充当瘦包装器的 C++/CLI 类对于 C 头文件中定义的数据结构,请从 C# 代码中引用 C++/CLI 包装类。这是最好的方法,还是有更好的方法?
2) 我遇到了参考问题。这是我的简化代码来说明问题:
C++/CLI 项目中的原始 C 头文件
#define ABC 0x12345
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;
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 指令或程序集引用?)。”
我以为我做了我应该做的一切。我应该怎么做才能修复这个错误?
【问题讨论】:
您是否确保首先编译 C++/CLI 项目(如在 C# 项目之前编译)?如果 C# 先编译并且没有为 CLI 项目生成 dll,它会这样说。 C++/CLI 命名空间是否在另一个命名空间中?使用对象浏览器进行查看。 你是否也在这两个项目之间放置了一个“项目依赖”...... @HansPassant C++/CLI项目中只有一个命名空间,如图所示。 @alexbuisson - 我检查了,C# 项目依赖于 C++/CLI 项目 【参考方案1】:在我自己的解决方案中,我有 4 个项目:
-
C++ 项目和测试代码
C++ DLL 项目,它只使用动态链接从第一个项目源中编译出 DLL
包装器项目,它只是一个使用 C++/CLI 的适配器,它包装了原始 C++
C# WPF 项目,这是我的图形界面。
这是我对上面提供的链接的翻译。
C++ DLL 项目
将您的 C++ 代码转换为 DLL 库。
-
在 Visual Studio 中,转到 文件 > 新建 > 项目,从 Visual C++ 选项卡中选择 Win32 项目。
为项目和解决方案选择一个名称,解决方案将包含所有项目。
在 Win32 应用程序助手中,点击下一步,勾选DLL框,然后选择Empty project,然后点击Finish强>。
要添加的代码
这是我的 dll 的 C++ 头文件(减去很多东西)。
令牌.h
#pragma once
#define DLLEXP __declspec( dllexport )
DLLEXP void pop_back(std::string& str);
DLLEXP std::string testReturnString();
DLLEXP int getRandomNumber();
CPP 内部没有什么可改变的。
构建项目,您应该有一个 DLL 和一个 LIB 文件以包含在 C# 项目调试目录中。
C++/CLI 包装器
此项目用作上一个项目的本机代码与 GUI 的托管代码之间的接口。
-
向解决方案添加一个新项目(Visual C++ 中的类库)(在本例中称为“Wrapper”)
使用附加的包含目录添加本机项目的路径
添加原生项目作为新项目的参考(右右键单击 > 参考... > 添加新链接)
在 Properties > Linker > Input 中,将本机 dll 的名称放在延迟加载 DLL(本例中为 Computations.dll)字段中
C++/CLI 代码
我的包装器只是一个看起来像这样的类(减去我自己的代码)。
包装器.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"
。
它还应该构建到一个 DLL 中,您将把它包含在 C# 调试目录中。
只是我在 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;
C# 项目
向解决方案添加一个新项目(C# Windows Form 或 WPF 或任何你想要的!)并将其设置为启动项目(right-点击 > 设置为启动项目)。
-
添加 C++/CLI 项目作为新项目的参考
以源代码形式添加指令
using Wrapper;
像这样使用它:
/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();
2016/05/06 更新
Ashwin 花时间制作了sample project 和blog post tutorial,这可能会有所帮助。
【讨论】:
由于某种原因我的公司阻止了您的链接:( 我正在我的答案中写一个小教程,不会很长! 瞧!我希望这应该能让你开始。 哇,感谢您花时间写这么多。但不幸的是,它对我帮助不大。首先,我不需要做一个本地 DLL 项目,因为除了一堆可以直接放入 C++/CLI 项目的 C 头文件之外,我没有本地代码。其次,创建了从 C# 项目到 C++/CLI 项目的引用,并且依赖项正确(C++/CLI 项目在 C# 项目之前构建)并且 C++/CLI DLL 已成功创建,但 C# 代码无法引用 C++/CLI 中的任何类(错误表示 C++/CLI 中的命名空间不存在或找不到)。如何解决这个问题? 谢谢,我已编辑我的答案以指向您的示例项目。【参考方案2】:对我来说,this 类似问题的答案解决了 C# 中的相同错误。
(即我的 C++\CLI 项目中有一个包装头文件,但也忘记包含一个 .cpp 文件(即使它只有两行:#include "stdafx.h" 和 #include " Wrapper.h"))
【讨论】:
以上是关于如何从 C# 访问 C++/CLI 中的类?的主要内容,如果未能解决你的问题,请参考以下文章