Implementation of a managed wrapper DLL I'm not entirely sure on how to handle errors on this:


Is returning a nullptr in case of bad parameters okay, or is it better to return a ENFMPCodegenData.Empty, like there is Rectangle.Empty or Point.Empty in the .NET Framework?
What about handling errors, if any should occur when creating the native object Codegen?
Should I just encompass this in a try / catch block and wrap a native exception inside  a managed one?


This my first attempt on creating such helper.  It's working, but I'm not really sure about its robustness.

public ref class ENMFPCodegen
{
    private:
        ENMFPCodegen()
        {
        }

    public:

        static ENMFPCodegenData ^ GetData ( array&lt;float&gt; ^ pcm , uint numberOfSamples, uint start_offset )
        {
            if ( pcm == nullptr || pcm-&gt;Length &lt;= 0  || numberOfSamples &lt;= 0 )
                return nullptr;

            pin_ptr&lt;float&gt; pFloat = &amp;pcm[0];
            Codegen * codegen = new Codegen ( pFloat, numberOfSamples, start_offset );

            if ( codegen == nullptr )
                return nullptr;

            std::string codeString = codegen-&gt;getCodeString();
            const char* chars = codeString.c_str();
            String ^ code = gcnew System::String ( chars );
            int numCodes =  codegen-&gt;getNumCodes();
            float version = codegen-&gt;getVersion();
            delete codegen;
            ENMFPCodegenData ^ data = gcnew ENMFPCodegenData ( code, numCodes, version );
            return data;
        }

};

public ref class ENMFPCodegenData {
    internal:
        ENMFPCodegenData ( String ^ code, int numCodes, float version )
        {
            Code = code;
            NumCodes = numCodes;
            Version = version;
        }

    public:
        String ^ Code;
        int NumCodes;
        float Version;

        virtual String ^ ToString() override
        {
            StringBuilder ^ sb = gcnew StringBuilder;
            sb-&gt;AppendFormat ( "{{Version: {0}, NumCodes: {1}, Code: {2}}}", Version, NumCodes, Code );
            return sb-&gt;ToString();
        }
};
Is returning a nullptr in case of bad parameters okay?


No, you should instead throw an ArgumentException (or possibly one of its derived types). This way, if an user of your code makes a mistake, they will get an exception clearly explaining the problem, instead of getting a confusing NullReferenceException at a later point.


  What about handling error if any should occur when creating the native object Codegen?


Again, you should throw a suitable .Net exception. In this case, I think a custom exception would be appropriate.


  Should I just encompass this in a try/catch block and wrap a native exception inside a managed one?


Not necessarily. Unmanaged exceptions are represented as the managed SEHException. So, if that's enough for you, you don't have to do anything.

But if you want to be able to handle some specific unmanaged exceptions from the managed code, or if you want to preserve some information from the unmanaged exception (SEHException doesn't really do that), you should catch the unmanaged exception and throw a new managed exception. For example:

public ref class UnmanagedException : Exception
{
public:
    UnmanagedException(String^ message)
        : Exception(message)
    {
    }
};

…

try
{
    // call some code that can throw std::exception here
}
catch (const std::exception &amp;ex)
{
    throw gcnew UnmanagedException(gcnew String(ex.what()));
}