【问题标题】:How to Use C++/CLI Within C# Application如何在 C# 应用程序中使用 C++/CLI
【发布时间】:2011-04-13 21:32:24
【问题描述】:

我正在尝试从我的 C# 应用程序(通过 C++/CLI)调用我的 C++ 库。我遵循this question 的示例(针对我的特定应用程序)。我的应用程序的设置是:

  • Project1:C++ 项目(我将其编译为 DLL)
  • Project2:C++ 项目(我的 CLR 包装器;只是上面示例中的头文件;参考 Project1)
  • Project3:C# 项目(参考 Project2)

不幸的是,当我实际访问 C# 应用程序中的 CLR 包装对象时,我收到以下错误:

类型或命名空间名称“YourClass” 找不到(您是否缺少 使用指令或程序集 参考?)

我的项目设置是否不正确,还是我应该研究其他什么? (不幸的是,由于专有原因,我无法发布代码,但这是一段非常简单的代码,很容易遵循上面的示例。)

更新:

所以我完全按照 Chris 说的去做(请参阅下面的答案),但我仍然收到来自我的 C# 应用程序的消息“找不到类型或命名空间名称‘MyProgram’(您是否缺少 using 指令还是程序集参考?)。这是我的代码的(模型)。

  • Project1 - 这是我的 C++ 应用程序。它编译/工作。我在别处用过。 (我从这个构建中得到了一个 DLL。)
  • Project2 - 这是我的包装器代码。

MyWrapper.h

#pragma once

#include "myorigapp.h"

using namespace System;

namespace MyProgram
{
    public ref class MyWrapper
    {
    private:
        myorigapp* NativePtr;

    public:
        MyWrapper() 
        {
            NativePtr = new myorigapp();
        }

        ~MyWrapper() 
        { 
            delete NativePtr;
            NativePtr = NULL;
        }

        void dostuff()
        { 
            NativePtr->dostuff(); 
        }
    }
}
  • Project3 - 这是我的 C# 应用程序。

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MyProgram;

namespace Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            MyWrapper p = new MyWrapper();
            p.dostuff();
        }
    }
}

Project3 引用 Project2 引用 Project1。一切都没有错误地构建(除了我上面在 using MyProgram 行的 C# 代码中描述的错误)。

【问题讨论】:

  • 您是否缺少 using 指令或程序集引用?
  • 应该发布一些代码,如果你不想发布原始的东西,也许你可以提取相关部分,简化和修改一些名称等。跨度>
  • @Hans @Doc - 用代码和更多信息更新了问题。

标签: c# .net command-line-interface


【解决方案1】:

仅包含来自纯 C++ 应用程序的标头是不够的。您需要用 Project2 中的托管对象包装您的非托管对象(即public ref class YourClassDotNet

#include "YourHeader.h"

namespace MyManagedWrapper
{
    public ref class YourClassDotNet
    {
    private:
        YourClass* ptr;

    public:
        YourClassDotNet()
        {
            ptr = new YourClass();
        }

        ~YourClassDotNet()
        {
            this->!YourClassDotNet();
        }

        !YourClassDotNet()
        {
            delete ptr;
            ptr = NULL;
        }

        void SomeMethod()
        {
            ptr->SomeMethod();
        }
    }
}

【讨论】:

  • +1。不要忘记提及MyManagedWrapper 的那些方法通常必须进行一些从 .NET 数据类型到本机 C++ 数据类型的类型转换,反之亦然。
  • @Doc: at your service,我猜?
  • 手动确保本地对象被正确释放会很快变得复杂。我建议使用智能指针而不是在每个包装类中复制该逻辑。 Here's one I wrote: scoped_ptr for C++/CLI (ensure managed object properly frees owned native object)
  • @Doc Brown 是的,那里变得很粗糙
  • @Chris - 谢谢你的回答。但是,我已经在这样做了。 Project1 和 Project2 确实构建正确。因此,我可能无法正确执行“使用”或程序集引用。你能提供对此的见解吗?据我所知(在您的示例中),我将从 Project3 中引用 Project2,并且在想要使用托管对象的 C# 类的顶部有“使用 MyManagedWrapper”。这是正确的吗?
【解决方案2】:

好吧,好吧,我现在感觉很笨。

事实证明,我遇到的问题(我在几周前解决了 - 刚刚开始更新这个答案)是我包含了头文件(请参阅 Chris 的答案),但我没有t 实际上包含了 CPP 文件(除了包含头文件之外,它是空的)。

完成此操作后,DLL 编译正确,我可以从我的 C# 代码调用 C++ 函数(使用 C++/CLI)。

【讨论】:

  • 我尝试了您的示例并生成了一个 dll,但我无法在 c# 程序中使用它。当我在对象浏览器中看到 dll 时,它是空的。我认为我不太了解您提出的解决方案。
  • 我现在遇到了同样的问题,但无法理解您的解决方案。也许你能解释一下?谢谢
【解决方案3】:

Chris 向您展示了创建托管类的方法,该类在内部使用非托管代码。在 C# 中使用 unsafe 可以做很多事情(只是几乎没有人这样做)。

但是,反过来也是可能的:直接从本机类型/函数使用 .NET 类型。

需要注意的是,任何托管指针都必须这样标记。为此,C++/CLI 定义了一个特殊类型的智能指针 gcroot<T>(在某种程度上模仿 boost::shared_pointer 或 std::auto_ptr)。因此,要将托管字符串存储在 C++ 类中,请使用以下命令:

#include <string>
#include <vcclr.h>
using namespace System;

class CppClass {
public:
   gcroot<String^> str;   // can use str as if it were String^
   CppClass(const std::string& text) : str(gcnew String(text.c_str())) {}
};

int main() {
   CppClass c("hello");
   c.str = gcnew String("bye");
   Console::WriteLine( c.str );   // no cast required
}

请注意(如果这些天尚未修复),您会因托管 null 和 C/C++ NULL 之间的不匹配而遇到一些摩擦。 正如您所料,您无法轻松输入:

gcroot<Object^> the_thing;
...
if (the_thing != nullptr)
 ...
}

相反,您必须使用本机样式(智能包装器 gcroot 处理此问题)

gcroot< Object^ > the_thing;
if ( the_thing != NULL ) {} // or equivalently...
if ( the_thing ) {}

// not too sure anymore, but I thought the following is also possible:
if ( the_thing != gcroot<Object>(nullptr) ) {}

注意: 这些天我无法访问 Windows 机器,所以我是凭记忆引用的

【讨论】:

  • 为了让它工作,您需要为项目打开 CLI(即这不适用于纯 C++ 应用程序)。
  • 或使用 /clr 标志编译
猜你喜欢
  • 1970-01-01
  • 2023-04-07
  • 2021-03-15
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多