如何从C#访问C ++ / CLI中的类?
我正在用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指令或程序集引用?)。”
我以为我做了我应该做的一切。 我该怎么做才能解决这个错误?
当我需要使用WPF将C ++链接到C#时,我发现这个链接非常有用。 不幸的是,它是用法语写的,所以我链接了谷歌提供的翻译版本。
在我自己的解决方案中,我有4个项目:
- C ++项目和测试代码
- C ++ DLL项目 ,它只使用动态链接从第一个项目源编译DLL
- 包装器项目 ,它只是一个使用C ++ / CLI的适配器,它包装了原始C ++
- C#WPF项目是我的图形界面。
这是我上面提供的链接的翻译。
C ++ DLL项目
将您的C ++代码转换为DLL库。
- 在Visual Studio中,转到文件>新建>项目 ,从Visual C ++选项卡中选择Win32项目 。
- 为项目和解决方案选择一个名称,解决方案将包含所有项目。
- 在Win32应用程序的助手中,单击下一步 ,选中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();
CPP内部没有任何改变。
构建项目,你应该有一个DLL和一个LIB文件包含在C#项目调试目录中。
C ++ / CLI包装器
该项目用作前一个项目的本机代码和GUI的托管代码之间的接口。
- 在解决方案中添加一个新项目(Visual C ++中的类库)(在此示例中称为“Wrapper”)
- 使用其他Include目录添加本机项目的路径
- 添加本机项目作为新项目的参考( 右键单击>引用…>添加新链接 )
- 在“ 属性”>“链接器”>“输入”中 ,将本机dll的名称放在DLL的延迟加载中(本例中为Computations.dll)字段
C ++ / CLI代码
我的包装器只是一个看起来像这样的类(减去我自己的代码)。
Wrapper.h
#include "Token.h" // include your C++ header #include #include 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); }; }
除了必须包含#include "stdafx.h"
之外,CPP中没有任何特殊内容。
它还应该构建一个DLL,你将包含在C#debug目录中。
只是一个有用的function,我发现在某处,但不记得你可能需要的地方。 它将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窗体或WPF或任何您想要的!)并将其设置为启动项目( 右键单击>设置为启动项目 )。
- 添加C ++ / CLI项目作为新项目的参考
-
using Wrapper;
添加指令using Wrapper;
源代码forms
使用它像:
/// Store the C++/CLI Wrapper object. private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();
更新2016/05/06
Ashwin花时间制作了一个示例项目和博客文章教程 ,可能会有所帮助。
对我来说, 这个类似问题的答案解决了C#中的同样错误。
(即我在C ++ \ CLI项目中有一个包装器头文件,但是忘了包含一个.cpp文件(尽管它只有两行:#include“stdafx.h”和#include“Wrapper.h “))