Search code examples
c++dllshared-ptr

How to create a shared_ptr in dll and export it via a factory function?


I have this pieces of code:

class DLL_API MyClassWrapper
{
private:

    MyClass * m_myClass;

public:
    MyClassWrapper(SIZE inputSize);
    ~MyClassWrapper();
     inline int OutputSize();

}
typedef  std::shared_ptr<MyClassWrapper> MyClassWrapperPtr;

extern "C"
{
     DLL_API MyClassWrapperPtr CreatreMyClassWrapper(SIZE inputSize)
     {
          return std::make_shared<MyClassWrapper>(inputSize);
      }
}

But it doesn't work, with error:

Error   1   error C2526: CreatreMyClassWrapper: C linkage function cannot return C++ class 'std::shared_ptr<_Ty>'   

I understand the problem, but how can I fix it?

The options that I can see are:

1- Don't pass a shared pointer. which means that DLL user should delete the pointer after they used it.

2- Don't use extern "C" : which means that I must use mangled names.

Is there any other solution?


Solution

  • Straight to the point, to return C++ object from C function - just returns it via output arguments:

    extern "C"
    {
         DLL_API void CreatreMyClassWrapper(SIZE inputSize, SomeClass* outputPtr)
         {
              *outputPtr = SomeClass(....);
         }
    }
    

    In your example SomeClass == MyClassWrapperPtr, so:

    extern "C"
    {
         DLL_API void CreatreMyClassWrapper(SIZE inputSize, MyClassWrapperPtr* outputPtr)
         {
              *outputPtr = make_shared<MyClassWrapper>(inputSize);
         }
    }
    

    Consider however to change your interface a little, because in current shape you need to be sure that your applications and DLLs shall use the same compiler, linker, settings, libraries...*

    You might want to export Create and Delete from your DLL to be sure memory management will occur in your DLL (this is based on this answer:

    DLL

    extern "C"
    {
         DLL_API MyClassWrapper* CreateMyClassWrapper(SIZE inputSize)
         {
              return new MyClassWrapper(inputSize);
         }
         DLL_API void DeleteMyClassWrapper(MyClassWrapper* wrapper)
         {
              delete wrapper;
         }
    }
    

    Application

         shared_ptr<MyClassWrapper> myClassWrapper(CreateMyClassWrapper(inputSize), 
                                                   DeleteMyClassWrapper);