2014-01-30 50 views
7

我從來沒有使用C++或C++/CLI,但我想在C#項目中使用本機C++庫。我搜索了一下,學習了一些關於C++/CLI的知識,並決定給它一個良好的開端。但我不確定我是否做得對。在C++/CLI中包裝本機C++結構

我有一個本地命名空間下struct

中avcodec.h

typedef struct AVCodecDescriptor { 
    enum AVCodecID  id; 
    enum AVMediaType type; 

    const char  *name; 
    const char *long_name; 
    int    props; 
} AVCodecDescriptor; 

現在我想換這個struct在C++/CLI在C#中使用它:

public ref struct AVCodecDescriptorWrapper { 

    private: 
     struct AVCodecDescriptor *_avCodecDescriptor; 

    public: 
     AVCodecDescriptorWrapper() { 
      _avCodecDescriptor = new AVCodecDescriptor(); 
     } 
     ~AVCodecDescriptorWrapper() { 
      delete _avCodecDescriptor; 
     } 

     // what do? 
     property AVCodecID Id { 
      AVCodecID get() { 
       return; // what comes here ???? 
      } 
     } 

}; 

但是,好像我正在做一些可怕的錯誤,因爲我甚至無法看到字段struct AVCodecDescriptor在C++/CLI中。我必須將結構中的enum包裝爲?我是否需要將它們複製到C++/CLI中並進行投射(好吧,enum AVCodecID有350個值 - 複製/粘貼似乎是嘲諷)。

+0

在這裏使用'new'和'delete'是沒有意義的。 'private:AVCodecDescriptor _avCodecDescriptor;'就足夠了。是的,你必須包裝一切。包括枚舉。您需要將它們聲明爲託管類型。然後將它們從非託管映射到託管。至於你打包的方式,你應該這樣做嗎?你將如何管理'const char *'成員的生命週期。坦率地說,對我來說C++/CLI比p/invoke更容易。 –

+2

@DavidHeffernan 1)private:AVCodecDescriptor _avCodecDescriptor不起作用,因爲VS告訴我我不能在託管類中使用非託管成員。 2)謝謝你澄清! 3)我還有什麼要包裝?這是很多教程處理它的方式。 4)我也不熟悉P/Invoke。但我需要從某個地方開始。我聽到很多人說P/Invoke會明顯變慢,因爲我正在使用的庫是ffmpeg ..好吧,你知道的。 – Acrotygma

+0

return(ManagedAVCodecID)_avCodecDescriptor-> id;你也需要一個終結者。很確定ffmpeg已經被封裝過了。儘管如此,許多死亡項目實際上完成似乎是一個很大的障礙。 –

回答

5

您需要創建本地結構和枚舉的等效CLI類。

public ref class ManagedAVCodecDescriptor { 
    ManagedAVCodecIDClass id; 
    ManagedAVMediaTypeClass type; 

    String^ name; 
    String^ long_name; 
    int props; 
}; 

枚舉等價類將是這樣的:

public enum class ManagedAVCodecIDClass 
{ 
    xyx = 1, 
    abc = 2, 
    ... 
} 

現在,在您AVCodecDescriptorWrapper你應該得到AVCodecDescriptor對象,並把在ManagedAVCodecDescriptor對象的所有信息,並把它傳遞給C#類。

ManagedAVCodecDescriptor^ mObject = gcnew ManagedAVCodecDescriptor(); 
mObject.setSomeValue(nativeStruct->somevalue); 

並將mObject傳遞給C#代碼作爲一般C#對象。

1

我更喜歡在本機代碼中使用.NET結構。 您定義:

public enum class AVCodecID : long 
{ 
    mp4 = 1, 
    mpeg2 = 2, 
    ... 

}

public ref class AVCodecDescriptor 
{ 
    AVCodecID id, 
    ... 
    System::String name 
    ... 
} 

,每當你在C++代碼需要你會打電話給

AVCodecDescriptor cd = gcnew AVCodecDescriptor(); 

它並不總是得心應手,你需要的文件使用它與/編譯clr開關,有時你可能會對轉換託管/非託管字符串感到生氣,但很多時候這對我來說非常合適。無論如何,您可以在C++本機代碼中輕鬆使用.NET枚舉,將枚舉值輸入爲int。

+0

本機結構已經存在;他們是現有本地圖書館的一部分。 –