Using unmanaged nested classes of a managed class 
Author Message
 Using unmanaged nested classes of a managed class

Hi,

I'm trying to wrap a library of unmanaged C++ classes to expose the
functionality as .Net classes. I use the technique outlined in several
articles on the Web and on the MSDN library CD, i.e. I wrap the
unmanaged class by constructing (with operator new) it in the
constructor of a managed class and destroying it in the destructor.
You know what I mean.

However, often I cannot simply forward calls from the managed class to
the unmanaged class it is wrapping. I need to use types such as
std::vector<> as members. Since these are unmanaged non-value types I
cannot make them members of the managed class. I need another
"translation layer".

My first instinct was to use the pimpl-idiom and create an unmanged
nested class that performs the translation and does other housekeeping
chores. Basically this is what my code looks like:

// in header
public __gc ManagedWrapper
{
public:
        ManagedWrapper();
~ ManagedWrapper();

void Foo();

private:
        __nogc class ManagedWrapperImpl;

ManagedWrapperImpl mImpl;

Quote:
};

// in implementation file

__nogc class ManagedWrapper::ManagedWrapperImpl
{
public:
        ManagedWrapperImpl();
~ManagedWrapperImpl();

void Foo();
private:
        LegacyClass*    mLegacyClass;

Quote:
};

ManagedWrapper::ManagedWrapperImpl:: ManagedWrapperImpl()
{
        mLegacyClass = new LegacyClass;

Quote:
}

ManagedWrapper::ManagedWrapperImpl::~ ManagedWrapperImpl()
{
        delete mLegacy;

Quote:
}

void ManagedWrapper::ManagedWrapperImpl::Foo()
{
// Do some stuff here to prepare Legacy

        // Call the Foo member on the legacy class
mLegacy->Foo();

Quote:
}

ManagedWrapper:: ManagedWrapper()
{
mImpl = new ManagedWrapperImpl;

Quote:
}

ManagedWrapper::~ ManagedWrapper()
{
        delete mImpl;

Quote:
}

void ManagedWrapper::Foo()
{
        mImpl->Foo();

Quote:
}

The code above (or something similar) compiles, but as soon as I try
to create a ManagedWrapper instance from C# code a TypeLoadException
is thrown.

I tried to wrap all the unmanged code in "#pragma unmanged - #pragma
manged"-pairs but that didn't help either.

I definitely have to use the implementation class. I cannot do all the
translation in the ManagedWrapper members. As alternatives I can use
an unmanaged implementation class by itself and not as a nested class,
which would produce another .h/.cpp pair of files, or declare an
interface IManagedWrapperImpl and derive the ManagedWrapperImpl from
in the .cpp file. The first alternative sort of breaks the
encapsulation of the implementation, while the second forces me to use
virtual functions (not a real objection, but not so clean as my
original idea). Both of them work actually.

Does anyone have any idea if what I'm trying to do is possible at all?
If not I'll have to resort to the alternatives.

Another issue (and a major showstopper) is that I'm unable to step
into unmanged code from managed code or even place a breakpoint in it.
If I cannot even do a basic thing like this I'll have to create an ATL
COM wrapper and use a COM object in t he C# code.

Any help is appreciated.

Svenne.



Mon, 24 May 2004 19:23:21 GMT  
 Using unmanaged nested classes of a managed class

Quote:
> Does anyone have any idea if what I'm trying to do is possible at all?
> If not I'll have to resort to the alternatives.

I do it the following way:
 typedef struct _unmanagedObjects  {
  LegacyClass m*_pLegacyClass;
  std::vector<int> m_Vector;
 } _unmanagedObjects;

 public __gc class Class1{
 public:
  Class1() {
   pInternal = new _unmanagedObjects;
  }
  ~Class1(){
   if (pInternal != 0)
   {
    delete pInternal;
    pInternal = 0;
   }
  }
 protected:
  _unmanagedObjects *pInternal;
 };

This works great...

Quote:
> Another issue (and a major showstopper) is that I'm unable to step
> into unmanged code from managed code or even place a breakpoint in it.
> If I cannot even do a basic thing like this I'll have to create an ATL
> COM wrapper and use a COM object in t he C# code.

I have no problem with this (if the unmanaged code is also compiled with the
actual build)

Greetings
 Jochen



Mon, 24 May 2004 20:16:20 GMT  
 Using unmanaged nested classes of a managed class

Quote:

> > Does anyone have any idea if what I'm trying to do is possible at all?
> > If not I'll have to resort to the alternatives.

> I do it the following way:
>  typedef struct _unmanagedObjects  {
>   LegacyClass m*_pLegacyClass;
>   std::vector<int> m_Vector;
>  } _unmanagedObjects;

>  public __gc class Class1{
>  public:
>   Class1() {
>    pInternal = new _unmanagedObjects;
>   }
>   ~Class1(){
>    if (pInternal != 0)
>    {
>     delete pInternal;
>     pInternal = 0;
>    }
>   }
>  protected:
>   _unmanagedObjects *pInternal;
>  };

> This works great...

That's the same solution as moving the implementation out into a
separate class (in a .h/.cpp pair) albeit slightly friendlier on the
keystrokes. I consider the internal organization of a class to be an
implementation detail, so I'd rather see _unmanagedObjects
inaccessible to clients of Class1. This is exactly what the pimpl
idiom in its strictest interpretation guarantees. However, if anything
else fails I will have to resort to tricks like that.

Sven.



Tue, 25 May 2004 15:11:16 GMT  
 Using unmanaged nested classes of a managed class
How about embedding a pointer to a std::vector instead?

Ronald Laeremans
Visual C++ compiler team



Quote:
> Hi,

> I'm trying to wrap a library of unmanaged C++ classes to expose the
> functionality as .Net classes. I use the technique outlined in several
> articles on the Web and on the MSDN library CD, i.e. I wrap the
> unmanaged class by constructing (with operator new) it in the
> constructor of a managed class and destroying it in the destructor.
> You know what I mean.

> However, often I cannot simply forward calls from the managed class to
> the unmanaged class it is wrapping. I need to use types such as
> std::vector<> as members. Since these are unmanaged non-value types I
> cannot make them members of the managed class. I need another
> "translation layer".

> My first instinct was to use the pimpl-idiom and create an unmanged
> nested class that performs the translation and does other housekeeping
> chores. Basically this is what my code looks like:

> // in header
> public __gc ManagedWrapper
> {
> public:
> ManagedWrapper();
> ~ ManagedWrapper();

> void Foo();

> private:
> __nogc class ManagedWrapperImpl;

> ManagedWrapperImpl mImpl;
> };

> // in implementation file

> __nogc class ManagedWrapper::ManagedWrapperImpl
> {
> public:
> ManagedWrapperImpl();
> ~ManagedWrapperImpl();

> void Foo();
> private:
> LegacyClass* mLegacyClass;
> };

> ManagedWrapper::ManagedWrapperImpl:: ManagedWrapperImpl()
> {
> mLegacyClass = new LegacyClass;
> }

> ManagedWrapper::ManagedWrapperImpl::~ ManagedWrapperImpl()
> {
> delete mLegacy;
> }

> void ManagedWrapper::ManagedWrapperImpl::Foo()
> {
> // Do some stuff here to prepare Legacy

> // Call the Foo member on the legacy class
> mLegacy->Foo();
> }

> ManagedWrapper:: ManagedWrapper()
> {
> mImpl = new ManagedWrapperImpl;
> }

> ManagedWrapper::~ ManagedWrapper()
> {
> delete mImpl;
> }

> void ManagedWrapper::Foo()
> {
> mImpl->Foo();
> }

> The code above (or something similar) compiles, but as soon as I try
> to create a ManagedWrapper instance from C# code a TypeLoadException
> is thrown.

> I tried to wrap all the unmanged code in "#pragma unmanged - #pragma
> manged"-pairs but that didn't help either.

> I definitely have to use the implementation class. I cannot do all the
> translation in the ManagedWrapper members. As alternatives I can use
> an unmanaged implementation class by itself and not as a nested class,
> which would produce another .h/.cpp pair of files, or declare an
> interface IManagedWrapperImpl and derive the ManagedWrapperImpl from
> in the .cpp file. The first alternative sort of breaks the
> encapsulation of the implementation, while the second forces me to use
> virtual functions (not a real objection, but not so clean as my
> original idea). Both of them work actually.

> Does anyone have any idea if what I'm trying to do is possible at all?
> If not I'll have to resort to the alternatives.

> Another issue (and a major showstopper) is that I'm unable to step
> into unmanged code from managed code or even place a breakpoint in it.
> If I cannot even do a basic thing like this I'll have to create an ATL
> COM wrapper and use a COM object in t he C# code.

> Any help is appreciated.

> Svenne.



Tue, 25 May 2004 23:22:02 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Using unmanaged class/data structure in managed class

2. Callback from unmanaged class to managed class...

3. Declaring unmanaged class in managed class.

4. Access managed class from unmanaged class

5. managed C++ wrapper around unmanaged C++ classes: causing StackOverflow exception

6. Freeing unmanaged memory within managed class

7. Making managed wrapper for legacy unmanaged classes.

8. Reference to an unmanaged pointer in a managed class

9. getting at a managed enum in an unmanaged class

10. Help me!! wrap unmanaged class with managed c++

11. Referencing data from unmanaged code to managed code in C++ Wrapper class

12. Inherit unmanaged c++ classes from .Net platform (managed c++ or c#)

 

 
Powered by phpBB® Forum Software