【问题标题】:Wrapper for DOTNET to native written in C++ CLI BestWay to pass structures?用 C++ CLI BestWay 编写的 DOTNET 到本机的包装器来传递结构?
【发布时间】:2011-07-19 12:33:15
【问题描述】:

但我正在 C++ CLI 中为我们的应用程序编写一个包装器,以保存一些新部分(用 C# 编写)并轻松访问旧的本机库。因此,我需要将一些结构从 C# 传递到 C++。这些结构在 C++ Cli (dotnet) 和 C++ 中定义。

例子:

\\C+++
typedef struct
{                                                           
INFO16   jahr   ;
INFO8    monat  ;
INFO8    tag    ;
INFO8    stunde ;
INFO8    minute ;
}
SDATUM;

\\c++ cli
[StructLayout(LayoutKind::Explicit)]
public value struct SDATUM
{
public:
  [FieldOffset(0)]
  UInt16 jahr;
  [FieldOffset(2)]
  Byte monat;
  [FieldOffset(3)]
  Byte tag;
  [FieldOffset(4)]
  Byte stunde;
  [FieldOffset(5)]
  Byte minute;
};

现在我在 C++ cli 中提供了一些函数,它们以按值传递、按引用 (sdatum%) 和指针 sdatum* 的形式将这种类型作为 dotnet 类型 SDATUM 接受,就像对应的本机函数一样。我需要什么来转换/转换这些结构?

【问题讨论】:

    标签: c# c++-cli native wrapper


    【解决方案1】:

    我不会做任何铸造。而是编写一个包含 SDATUM 的 ref 类。公开设置基础 SDATUM 的方法和属性。从 C# 端,使用这个 ref 类(或者更好的是,创建一个该类实现的接口并让 C# 端使用该接口)。在 C++/CLI 中,您可以访问本机版本的类并根据需要将其传递给本机方法。

    【讨论】:

      【解决方案2】:

      请注意,C++ 和 .NET 的复制语义根本不同:.NET 使用垃圾收集共享引用,而 C++ 使用复制构造函数。

      C++/CLI 不允许您使用本地对象作为托管类的成员,您必须使用指针。所以我将使用 boost 共享指针来模仿 .NET 语义。

      这可以被抽象掉。这是我用来向 .NET 世界公开 C++ 类的类:

      template <typename T>
      ref class Handle
      {
          boost::shared_ptr<T>* t;
      
          !Handle() 
          {
              if (t != nullptr)
              {
                  delete t;
                  t = nullptr;
              }
          }
      
          ~Handle() { this->!Handle(); }
      
      public:
          Handle() : t(new boost::shared_ptr<T>((T*)0)) {}
      
          Handle(T* ptr) : t(new boost::shared_ptr<T>(ptr)) {}
      
          Handle% operator=(T* p)
          {
              if (p != t->get()) t->reset(p);
              return *this;
          }
      
          T* get() { return t->get(); }
      
          // Remember that operators are static in .NET
          static boost::shared_ptr<T> operator->(Handle% h) { return *h.t; }
      
          T& reference() { return *t->get(); }
          T const& const_reference() { return *t->get(); }
      };
      

      那么你可以使用:

      ref class MyStruct
      {
      public:
          // Expose your .NET interface here, make it use the handle variable.
      
      internal:
          Handle<Native::MyStruct> handle;
      };
      

      并在您的 C++ 代码中不受限制地使用 handle 成员变量。它不会在 .NET 中显示。然后,您可以以 .NET 方式公开属性、访问器、运算符等。

      【讨论】:

      • 这是一个非常好的模板,但不幸的是我无法使用 boost。我会尝试在没有提升的情况下实现它
      【解决方案3】:

      我找到了另一个非常简单、简短且不需要复制数据的解决方案。 您可以通过这种方式调用需要 C SDATUM 的本机函数:

      //signature
      void someFunction(SDATUM datum);
      
      void someFunctionWrapper(SDATUM datum){
      pin_ptr<SDATUM>  datum_pin=&datum;
      
      
      //::SDATUM refers to the C-Type
      someFunction(*(::SDATUM*)datum_pin);
      }
      

      我对其进行了测试,它可以正常工作,因为两个 SDATUM 结构具有相同的位结构。因为我只打电话 短原生函数我觉得分片没问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 2016-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-12
        • 1970-01-01
        相关资源
        最近更新 更多