C ++ / CLI模板封装 [英] C++/CLI template wrapper round

查看:211
本文介绍了C ++ / CLI模板封装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组具有相同接口的多个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆