C ++ / CLI模板包装器回合

时间:2016-09-16 13:20:59

标签: c++ templates generics c++-cli

我有一组具有相同接口的多个C ++类(虽然不是相互派生的)。我试图将它们包装起来,以便在.NET中使用它们。

我目前有一个使用C / C ++ #defines定义包装类的方法,然后我可以用简单的代码行实例化类

但是我无法调试这个。理想情况下,我希望能够使用通用或模板。但是,我不能在泛型中使用C ++类型,这将是解决此问题的最终方法。

有没有人知道如何在不使用可怕的宏的情况下做到这一点?

编辑

OK这是我写过的模板化课程的一个例子:

       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 个答案:

答案 0 :(得分: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) {}
    };

};

果然,C#可以看到ManagedWrapperAManagedWrapperB。也许你可以宏这些定义,并且仍然可以获得不错的调试体验。