Reputation: 355
I'm new to C# and C++/CLI and not quite familiar with them. I searched but couldn't find an existing solution for a pretty simple thing (which I suppose should be common).
I am writing a simple C++/CLI project (a wrapper to C++ native dlls to be used in C#). There are many examples how to write a wrapper for native class:
class CNativeClass {
CNativeClass() {}
void Foo() {}
}
public ref class CNativeClassWrapper {
public:
CNativeClassWrapper() {
_Wrapper = new CNativeClass;
}
~CNativeClassWrapper() {
this->!CNativeClassWrapper();
}
!CNativeClassWrapper() {
delete _Wrapper;
_Wrapper = nullptr;
}
void Foo() {
_Wrapper->Foo();
}
private:
CNativeClass* _Wrapper;
}
This is simlified example code. There may be more native classes, there may be late initialization... A lot minor but necessary code.
Is there any wrapper for variable of native class which hides all these details? Like smart pointer templates in pure C++.
Moreover, if a native class is actually a smart pointer (90% of my cases, we use boost::shared_ptr<>) the code becomes a mess:
if ( _Wrapper )
or if ( *_Wrapper )
or even if ( _Wrapper && *_Wrapper )
,(*_Wrapper)->Foo();
,(*_Wrapper).reset();
and _Wrapper->reset();
are correct but it is too confusing.Does anybody know a solution for this?
Upvotes: 3
Views: 2946
Reputation: 355
Well, I have finally come to such wrapper classes:
for holding general native classes:
template <class T>
public ref class native_auto_ptr
{
public:
native_auto_ptr()
{
_pNative = new T;
}
native_auto_ptr(const native_auto_ptr<T>% rhs)
{
_pNative = new T( *rhs._pNative );
}
~native_auto_ptr()
{
reset();
}
void reset()
{
delete _pNative;
_pNative = nullptr;
}
T* ptr()
{
return _pNative;
}
T* operator->()
{
return _pNative;
}
operator bool()
{
return _pNative;
}
void operator=(const native_auto_ptr<T>% rhs)
{
*_pNative = *rhs._pNative;
}
void operator=(const T% rhs)
{
*_pNative = rhs;
}
protected:
!native_auto_ptr()
{
reset();
}
private:
T* _pNative;
};
for holding shared_ptr<>
:
template <class T>
public ref class native_shared_ptr
{
public:
native_shared_ptr()
{
_spNative = new boost::shared_ptr<T>;
}
native_shared_ptr(const native_shared_ptr<T>% rhs)
{
_spNative = new boost::shared_ptr<T>;
*this = rhs;
}
native_shared_ptr(const boost::shared_ptr<T>% rhs)
{
_spNative = new boost::shared_ptr<T>( rhs );
}
~native_shared_ptr()
{
reset();
}
void reset()
{
delete _spNative;
_spNative = nullptr;
}
T* operator->()
{
return _spNative->get();
}
operator bool()
{
return _spNative && *_spNative;
}
void operator=(const native_shared_ptr<T>% rhs)
{
*_spNative = *rhs._spNative;
}
void operator=(const boost::shared_ptr<T>% rhs)
{
*_spNative = rhs;
}
protected:
!native_shared_ptr()
{
reset();
}
private:
boost::shared_ptr<T>* _spNative;
};
I am quite happy :)
The only issue is with the ctors with parameters... (TBD)
Upvotes: 2
Reputation: 699
I don't think there is a build-in class shipped with the C++/CLI framework, but you can easily design your own.
Take a look at this question: auto_ptr or shared_ptr equivalent in managed C++/CLI classes
I would not use smart pointers. The managed wrapper to the native object will take care of releasing the native object when the containing managed class is disposed or finalized.
Upvotes: 0