如何从 C# 访问 C++/CLI 中的类? [英] How to access class in C++/CLI from C#?

查看:36
本文介绍了如何从 C# 访问 C++/CLI 中的类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 C# 编写一个 GUI 工具来解析和显示另一个用 C 编写的程序的数据输出.为了解析数据,我需要知道在许多 C 头文件中指定的数据结构.因此,我需要将这些 C 头文件合并到我的 C# 项目中.我的问题是:

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:

1) 经过一些研究,我得出结论,最好的方法是在我的解决方案中创建一个新的 C++/CLI 项目,将 C 头文件导入这个新项目,编写一些充当瘦包装器的 C++/CLI 类对于 C 头文件中定义的数据结构,然后从 C# 代码中引用 C++/CLI 包装类.这是最好的方法,还是有更好的方法?

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?

2) 我遇到了参考问题.这是我的简化代码来说明问题:

2) I ran into a reference problem. Here's my simplified code to illustrate the problem:

C++/CLI 项目中的原始 C 头文件

Original C header in C++/CLI project

#define ABC  0x12345

C++/CLI 项目中的包装类

Wrapper class in C++/CLI project

#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 指令或程序集引用?)."

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?)."

我以为我做了我应该做的一切.我应该怎么做才能修复这个错误?

I thought I did everything I was supposed to. What should I do to fix this error?

推荐答案

在我自己的解决方案中,我有 4 个项目:

In my own solution, I had 4 projects:

  1. C++ 项目和测试代码
  2. C++ DLL 项目,仅使用动态链接从第一个项目源中编译 DLL
  3. 包装器项目,它只是一个使用 C++/CLI 的适配器,它包装了原始 C++
  4. C# WPF 项目,这是我的图形界面.
  1. the C++ project and the test code
  2. the C++ DLL project which only compiles a DLL out of the first project source using dynamic links
  3. the wrapper project which is only an adapter using C++/CLI, which wraps around the raw C++
  4. the C# WPF project which was my graphical interface.

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

Here's my translation of the provided link above.

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

Make your C++ code into a DLL lib.

  1. 在 Visual Studio 中,转到 File > New > Project,从 Visual C++ 选项卡中选择 Win32 project.
  2. 为项目和解决方案选择一个名称,解决方案将包含所有项目.
  3. 在 Win32 应用程序助手中,点击下一步,勾选DLL框,然后点击Empty project,然后点击Finish强>.
  1. Inside Visual Studio, go to File > New > Project, Select Win32 project from 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 DLL box, then Empty project then click Finish.

这是我的 dll 的 C++ 头文件(减去很多东西).

This is my C++ header for the dll (minus lot of stuff).

令牌.h

#pragma once
#define DLLEXP   __declspec( dllexport )

DLLEXP void pop_back(std::string& str);

DLLEXP std::string testReturnString();

DLLEXP int getRandomNumber();

CPP 内部没有什么可改变的.

There's nothing to change inside the CPP.

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

Build the project, you should have a DLL and a LIB file to include in the C# project debug dir.

此项目用作上一个项目的本机代码与 GUI 的托管代码之间的接口.

This project serves as an interface between the native code from the previous project, and managed code of the GUI.

  1. 向解决方案添加一个新项目(Visual C++ 中的类库)(在本例中称为Wrapper")
  2. 使用附加的包含目录添加本机项目的路径
  3. 将本机项目添加为新项目的参考(右键单击 > 参考... > 添加新链接)
  4. Properties > Linker > Input中,将本机dll的名称放在延迟加载DLL(本例中为Computations.dll)字段中
  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

C++/CLI 代码

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

The C++/CLI code

My wrapper is only a class which looks something like this (minus my own code).

包装器.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".

Nothing special inside the CPP except that you have to include #include "stdafx.h".

它还应该构建到一个 DLL 中,您将把它包含在 C# 调试目录中.

It should also builds into a DLL which you will include inside the C# debug dir.

只是我在 SO 某处找到的一个有用功能,但不记得您可能需要的位置.它将 C++/CLI 字符串句柄转换为 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.

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 FormWPF 或任何你想要的!)并将其设置为启动项目(right-点击 > 设置为启动项目).

The C# project

Add to the solution a new project (C # Windows Form or WPF or whatever you want!) and set it as the startup project (right-click > set as startup project).

  1. 添加 C++/CLI 项目作为新项目的参考
  2. 以源代码形式添加指令using Wrapper;

像这样使用它:

/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();

2016/05/06 更新

阿什温 花时间制作了一个 示例项目 和一个 博文教程可能会有所帮助.

Ashwin took the time to make a sample project and a blog post tutorial which may help further.

这篇关于如何从 C# 访问 C++/CLI 中的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆