如何从C#访问C++/CLI中的类?

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个项目:

  1. C++项目和测试代码
  2. C++ DLL项目只使用动态链接编译一个DLL出的第一个项目的源
  3. 包装项目,其是仅使用C++/CLI,其周围的纯粹的C包装一个适配器++
  4. C#WPF项目这是我的图形界面.

这是我上面提供的链接的翻译.

C++ DLL项目

将您的C++代码转换为DLL库.

  1. 在Visual Studio中,转到文件>新建>项目,从Visual C++选项卡中选择Win32项目.
  2. 选择项目和解决方案的名称,解决方案将包含所有项目.
  3. 在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();
Run Code Online (Sandbox Code Playgroud)

CPP内部没有任何改变.

构建项目,你应该有一个DLL和一个LIB文件包含在C#项目调试目录中.

C++/CLI包装器

该项目用作前一个项目的本机代码和GUI的托管代码之间的接口.

  1. 在解决方案中添加一个新项目(Visual C++中的类库)(在此示例中称为"Wrapper")
  2. 使用其他Include目录将路径添加到本机项目
  3. 添加本机项目作为新项目的参考(右键单击>引用...>添加新链接)
  4. 在" 属性">"链接器">"输入"中,将本机dll的名称放在DLL的延迟加载中(本例中为Computations.dll)字段

C++/CLI代码

我的包装器只是一个看起来像这样的类(减去我自己的代码).

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#项目

向解决方案添加一个新项目(C#Windows窗体WPF或任何您想要的!)并将其设置为启动项目(右键单击>设置为启动项目).

  1. 添加C++/CLI项目作为新项目的参考
  2. 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花时间制作了一个示例项目博客文章教程,可能会有所帮助.


Bar*_*tel 5

对我来说,这个类似问题的答案解决了C#中的相同错误.

(即我在C++\CLI项目中有一个包装器头文件,但是忘了包含一个.cpp文件(尽管它只有两行:#include"stdafx.h"和#include"Wrapper.h "))