C++/CLI template wrapper round

浪子不回头ぞ 提交于 2019-12-25 09:12:27

问题


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 ...


回答1:


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.



来源:https://stackoverflow.com/questions/39532564/c-cli-template-wrapper-round

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!