2
\$\begingroup\$

Background: I'm writing C++ code after a fairly long time, so I may not be up to date on the best practices, so please bear with me. I'm only trying to improve and learn.

Problem I need to write a wrapper in C++/CLI for a C++ library so that I can use it in C#. The limitation that C++/CLI managed types can only contain pointers to native types is very frustrating. Part of the reason is that the native library I'm wrapping around has classes that are often passed around among themselves as shared_ptr or native references to instances.

Code My code is inspired by this post but I'm trying to use shared_ptrs instead of the raw pointers.

#pragma once
#include <memory>

namespace App
{
    using namespace System;

    template<typename T>
    public ref class Managed
    {
    private:
        std::shared_ptr<T>* native;

    protected:
        !Managed()
        {
            delete native;
        }

    private protected:
        // Allows derived classes to construct native objects with parameters
        // but only accepts shared_ptr
        Managed(std::shared_ptr<T> t) : native(new std::shared_ptr<T>(t)) {}

        // Assumes default constructor for the native object
        Managed() : Managed(std::make_shared<T>()) {}

    internal:

        /*
        Return a reference to the native object
        */
        [CLSCompliantAttribute(false)]
        property T& WrappedObject
        {
            T& get()
            {
                return **native;
            }
        }

        /*
        Return a shared pointer by value to the native object
        */
        [CLSCompliantAttribute(false)]
        property std::shared_ptr<T> WrappedPointer
        {
            std::shared_ptr<T> get()
            {
                return *native;
            }
        }

    public:
        virtual ~Managed()
        {
            this->!Managed();
        }
    };
}

The wrapper can be used like so (this is just an example, not something I'm actually using):

public ref class NativeObjWrapper: Managed<NativeObj>
{
public:
        NativeObjWrapper(int x) : Managed<NativeObj>(std::make_shared<NativeObj>(x)) {}

        NativeObjWrapper() {}

        // Example for passing by reference
        void SetPropertyByReference(AnotherNativeObjWrapper^ another)
        {
            WrappedObject.setProperty(another.WrappedObject);
        }
}

If somebody could take a look and point some obvious flaws that I'm overlooking, that'd be great.

\$\endgroup\$
2
  • \$\begingroup\$ I think you are a bit confusing about the share_ptr, the share_ptr is a smart pointer by him self, that don't needs to be a pointer as "std::shared_ptr<T>* native" you show. Remove the * and fix your code like "std::shared_ptr<T> native". \$\endgroup\$ – camp0 Apr 22 '20 at 11:17
  • \$\begingroup\$ @oczkoisse Long time after your question, but was this code used on production? Is it safe to use as a reference? \$\endgroup\$ – Valmir Oct 21 '20 at 15:32

Browse other questions tagged or ask your own question.