簡體   English   中英

如何在C#應用程序中使用C ++ / CLI

[英]How to Use C++/CLI Within C# Application

我試圖從我的C#應用​​程序(通過C ++ / CLI)調用我的C ++庫。 我按照這個問題的例子(針對我的具體應用)。 我的應用程序的設置是:

  • Project1:C ++項目(我將其編譯為DLL)
  • Project2:C ++ Project(我的CLR包裝器;只是上面例子中的頭文件;引用Project1)
  • Project3:C#項目(參考Project2)

不幸的是,當我真正去訪問我的C#應用​​程序中的CLR包裝器對象時,我收到以下錯誤:

找不到類型或命名空間名稱'YourClass'(您是否缺少using指令或程序集引用?)

我是否錯誤地設置了項目,或者還有其他我應該研究的內容? (不幸的是,我不能出於專有原因發布代碼,但這是一個非常簡單的代碼,很容易遵循上面的例子。)

更新:

所以我完全按照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引用引用Project1的Project2。 一切都沒有錯誤地構建(除了上面在using MyProgram線的C#代碼中描述的錯誤)。

僅僅包含純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();
        }
    }
}

好吧,我現在感到愚蠢。

事實證明我遇到的問題(幾周前我解決了 - 只是更新了這個答案)就是我已經包含了頭文件(請參閱Chris的答案),但我實際上沒有包括CPP文件(除了包含頭文件之外是空的)。

一旦我這樣做,DLL編譯正確,我可以從我的C#代碼調用C ++函數(使用C ++ / CLI)。

Chris向您展示了創建使用非托管代碼的托管類的方法。 你可以在C#中使用不安全的東西(很少有人這么做)。

但是,反過來也是可能的:直接從本機類型/函數使用.NET類型。

需要注意的是,任何托管指針都必須標記為這樣。 為此,C ++ / CLI定義了一種特殊類型的smartpointer 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機器,因此我引用了內存

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM