2014-01-30 32 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

本机结构已经存在;他们是现有本地图书馆的一部分。 –