2016-09-16 123 views
0

我有一組多個C++類具有相同的接口(但不是彼此派生)。我試圖包裝這些,使他們在.NET中可用。C++/CLI模板包裝輪

我現在有限定用C/C++的#define包裝類的方法,然後我可以隨後實例化類用代碼

一個簡單的線然而我不能調試此。理想情況下,我希望能夠使用通用或模板。不過,我不能在通用內部使用C++類型,這將是解決此問題的最終方法。

有沒有人有任何想法,我怎麼能做到這一點,而不使用可怕的宏?

編輯

確定這裏是我寫的模板類的一個實例:

 template< typename CPPResamplerClass > 
     ref class TResampler 
     { 
      CPPResamplerClass* pResampler; 
     public: 

      TResampler(int inputSampleRate, int outputSampleRate, int bufferLen) : 
       pResampler(new CPPResamplerClass(inputSampleRate, outputSampleRate, bufferLen)) 
      { 

      } 

      ~TResampler() 
      { 
       this->!ResamplerName(); 
      } 

      !TResampler() 
      { 
       if (pResampler) 
       { 
        delete pResampler; 
        pResampler = nullptr; 
       } 
      } 

      property int HistorySize 
      { 
       int get() 
       { 
        return pResampler->HistorySize(); 
       } 
      } 

      array<float>^ ResampleAudio(array<float>^ in) 
      { 
       pResampler->Get 
        array<float>^ out = gcnew array<float>(in->Length); 
       cli::pin_ptr<float> pIn = &in[0]; 
       cli::pin_ptr<float> pOut = &out[0]; 

       unsigned int inLen = in->Length; 
       unsigned int outLen = out->Length; 

       if (pResampler->ResampleAudio(pOut, outLen, pIn, inLen)) 
       { 
        System::Array::Resize(out, outLen); 
        return out; 
       } 
       return nullptr; 
      } 
     }; 

     typedef TResampler<::Vec::SpeexResample> SpeexResample; 

那麼我想從C#訪問此然而SpeexResample不存在。這可能是因爲我正在使用typedef ...

+1

這個問題*絕對*需要一些示例代碼。作爲高級代表用戶,您應該知道[mcve]是什麼... –

+0

模板是C++的細節,對任何其他.NET語言都沒有用處。改爲使用'generic'關鍵字。 –

+0

@HansPassant:但我不能使用C++類型作爲泛型類的參數...我可以嗎?如果我可以......你能解釋一下,因爲那是我問題的癥結所在! ;) – Goz

回答

1

模板在實例化之前不存在。雖然你可以實例化一個明確的:

template ref class TResampler<SomeNativeClass>; 

它將不完全用戶友好的使用從C#。輸出類型字面上名稱中有尖括號。祝好運使用。在C#中,它只能通過反射來實現。

下一個最好的事情是使用派生類型。這裏有一個小例子:

#include "stdafx.h" 
#include <iostream> 

namespace CppCli { 

    class NativeClassA 
    { 
     int foo; 

    public: 
     NativeClassA(int foo) : foo(foo) { std::cout << "Built native class A" << std::endl; } 
     int getFoo() const { return foo; } 
    }; 

    class NativeClassB 
    { 
     int foo; 

    public: 
     NativeClassB(int foo) : foo(foo) { std::cout << "Built native class B" << std::endl; } 
     int getFoo() const { return foo; } 
    }; 

    template<typename NativeClass> 
    public ref class ManagedWrapper 
    { 
     NativeClass* ptr; 

    public: 
     ManagedWrapper(int foo) 
      : ptr(new NativeClass(foo)) 
     {} 

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

     !ManagedWrapper() 
     { 
      if (ptr) 
      { 
       delete ptr; 
       ptr = nullptr; 
      } 
     } 

     property int Foo { int get() { return ptr->getFoo(); } } 
    }; 

    public ref class ManagedWrapperA : ManagedWrapper<NativeClassA> 
    { 
    public: 
     ManagedWrapperA(int foo) : ManagedWrapper(foo) {} 
    }; 

    public ref class ManagedWrapperB : ManagedWrapper<NativeClassB> 
    { 
    public: 
     ManagedWrapperB(int foo) : ManagedWrapper(foo) {} 
    }; 

}; 

果然,ManagedWrapperAManagedWrapperB是從C#可見。也許你可以宏觀這些的定義,並仍然有一個體面的調試體驗。

+0

感謝您的迴應,我沒有發現它到達並正在處理其他事情。我會看看如果我可以得到這個工作。目前它給了我一個編譯器堆棧溢出,但它看起來很有前途。 – Goz