patterncsharpMinor
Implementation of a managed wrapper DLL
Viewed 0 times
managedimplementationwrapperdll
Problem
I'm not entirely sure on how to handle errors on this:
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 ^ pcm , uint numberOfSamples, uint start_offset )
{
if ( pcm == nullptr || pcm->Length pFloat = &pcm[0];
Codegen * codegen = new Codegen ( pFloat, numberOfSamples, start_offset );
if ( codegen == nullptr )
return nullptr;
std::string codeString = codegen->getCodeString();
const char* chars = codeString.c_str();
String ^ code = gcnew System::String ( chars );
int numCodes = codegen->getNumCodes();
float version = codegen->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->AppendFormat ( "{{Version: {0}, NumCodes: {1}, Code: {2}}}", Version, NumCodes, Code );
return sb->ToString();
}
}
- Is returning a
nullptrin case of bad parameters okay, or is it better to return aENFMPCodegenData.Empty, like there isRectangle.Emptyor 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/catchblock 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 ^ pcm , uint numberOfSamples, uint start_offset )
{
if ( pcm == nullptr || pcm->Length pFloat = &pcm[0];
Codegen * codegen = new Codegen ( pFloat, numberOfSamples, start_offset );
if ( codegen == nullptr )
return nullptr;
std::string codeString = codegen->getCodeString();
const char* chars = codeString.c_str();
String ^ code = gcnew System::String ( chars );
int numCodes = codegen->getNumCodes();
float version = codegen->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->AppendFormat ( "{{Version: {0}, NumCodes: {1}, Code: {2}}}", Version, NumCodes, Code );
return sb->ToString();
}
}
Solution
Is returning a
No, you should instead throw an
What about handling error if any should occur when creating the native object
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
Not necessarily. Unmanaged exceptions are represented as the managed
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 (
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 &ex)
{
throw gcnew UnmanagedException(gcnew String(ex.what()));
}Code Snippets
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 &ex)
{
throw gcnew UnmanagedException(gcnew String(ex.what()));
}Context
StackExchange Code Review Q#23916, answer score: 3
Revisions (0)
No revisions yet.