C ++ / CLI模板封装 [英] C++/CLI template wrapper round
问题描述
我有一组具有相同接口的多个C ++类(不是相互派生的)。我试图包装这些,使他们在.NET中可用。
我现在有一个方法使用C / C ++ #defines定义包装类,然后我可以用一行简单的代码实例化类。
但是我无法调试。理想情况下,我希望能够使用通用或模板。不过,我不能在通用内部使用C ++类型,这将是解决此问题的最终方法。
有没有人知道如何在不使用可怕的宏的情况下做到这一点?
$ b 编辑 :
确定下面是我编写的模板类的示例:
模板< 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;
属性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<浮动> pIn =& in [0];
cli :: pin_ptr<浮动> pOut =& out [0];
unsigned int inLen = in->长度;
unsigned int outLen = out->长度;
if(pResampler-> ResampleAudio(pOut,outLen,pIn,inLen))
{
System :: Array :: Resize(out,outLen);
退出;
}
返回nullptr;
}
};
typedef TResampler< :: Vec :: SpeexResample> SpeexResample;
然后我想从C#访问它,但是 SpeexResample
不存在。这可能是因为我使用了typedef ...
模板不会直到它们被实例化。虽然你可以明确地实例化一个:
template ref class TResampler< SomeNativeClass>;
从C#使用它并不完全用户友好。导出的类型字面上的名称中有尖括号。使用 祝你好运。在C#中,它只能通过反射来实现。
接下来最好的事情是使用派生类型。这里有一个简单的例子:
$ b
#includestdafx.h
#include< ;&的iostream GT;
namespace CppCli {
class NativeClassA
{
int foo;
public:
NativeClassA(int foo):foo(foo){std :: cout<< 构建的本地A类<<的std :: ENDL; }
int getFoo()const {return foo; }
};
class NativeClassB
{
int foo;
public:
NativeClassB(int foo):foo(foo){std :: cout<< 构建的本地类B<<的std :: ENDL; }
int getFoo()const {return foo; }
};
模板< typename NativeClass>
public ref class ManagedWrapper
{
NativeClass * ptr;
$ b $ 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){}
};
};
果然, ManagedWrapperA
和 ManagedWrapperB
在C#中可见。也许你可以宏这些定义,仍然有一个体面的调试体验。
I have a set of multiple C++ classes that have the same interface (not derived from each other though). I'm trying to wrap these to make them available in .NET.
I currently have a method that defines the wrapper class using C/C++ #defines and then I can subsequently instantiate classes with a simple line of code
However I can't debug this. Ideally I would like to be able to use a generic or a template. However I can't use a C++ type inside a generic which would be the ultimate way to solve this problem.
Has anyone any idea of how I can do this without using the dreaded macros?
EDIT:
OK Here is an example of the templated class I have written:
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;
I then want to access this from C# however SpeexResample
does not exist. This could well be because I am using a typedef ...
Templates don't exist until they're instantiated. While you could instantiate one explicitly:
template ref class TResampler<SomeNativeClass>;
It wouldn't be exactly user-friendly to use from C#. The exported type will literally have angle brackets in its name. Good luck using that. In C# it's only doable through reflection.
The next best thing is to use derived types. Here's a minimal example:
#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) {}
};
};
Sure enough, ManagedWrapperA
and ManagedWrapperB
are visible from C#. Maybe you could macro these definitions and still get a decent debugging experience.
这篇关于C ++ / CLI模板封装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!