如何从 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:16:58  来源:igfitidea点击:

How to access class in C++/CLI from C#?

c#dependenciesc++-clidependency-management

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

  1. the C++ projectand the test code
  2. the C++ DLL projectwhich only compiles a DLL out of the first project source using dynamic links
  3. the wrapper projectwhich is only an adapter using C++/CLI, which wraps around the raw C++
  4. the C# WPF projectwhich was my graphical interface.
  1. C ++项目和测试代码
  2. 仅使用动态链接从第一个项目源中编译 DLL的C++ DLL 项目
  3. 包装项目,其是仅使用C ++ / CLI,其周围的纯粹的C包装一个适配器++
  4. 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 库。

  1. Inside Visual Studio, go to File > New > Project, Select Win32 projectfrom the Visual C++ tab.
  2. Choose a name for both the project and the Solution, the solution will have all the projects inside.
  3. Inside the assistant for Win32 Application, click next, check the DLLbox, then Empty projectthen click Finish.
  1. 在 Visual Studio 中,转到File > New > Project,从 Visual C++ 选项卡中选择Win32 项目
  2. 为项目和解决方案选择一个名称,解决方案将包含所有项目。
  3. 在 Win32 Application 助手中,单击next,选中DLL框,然后Empty project ,然后单击Finish

Project creationProject assistant

项目创建项目助手

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 的托管代码之间的接口。

  1. Add a new project (class library in Visual C++) (called "Wrapper" in this example) to the solution
  2. Add the path to the native project with the additional Include directories
  3. Add the native project as a reference for the new project (right click > References... > Add New Link)
  4. In Properties > Linker > Input, put the name of the native dll in the delayed loading of DLLs (Computations.dll in this example) field
  1. 向解决方案添加一个新项目(Visual C++ 中的类库)(在本例中称为“Wrapper”)
  2. 使用额外的 Include 目录添加本机项目的路径
  3. 添加本机项目作为新项目的引用(右键单击 > 引用... > 添加新链接
  4. 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或任何您想要的!)并将其设置为启动项目(右键单击 > 设置为启动项目)。

  1. Add the C++/CLI project as a reference for the new project
  2. Add Directive using Wrapper;in source code form
  1. 添加 C++/CLI 项目作为新项目的参考
  2. 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.

Ashwin花时间制作了一个示例项目和一个博客文章教程,这可能会有所帮助。

回答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 "))