2016-09-16 79 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