Managed C++ wrapper with abstract base return types

G

Guest

I am trying to create an Managed C++ Wrapper around an unmanaged library
which contains C++ code.

Some of the unmanaged methods returns an returntype which is of the abstract
base type (for example unmanagedObject). How can i convert this to the
managed abstract basetype?

Hope somebody can help me

Thanx
 
I

Ioannis Vranos

WithPit said:
I am trying to create an Managed C++ Wrapper around an unmanaged library
which contains C++ code.

Some of the unmanaged methods returns an returntype which is of the abstract
base type (for example unmanagedObject). How can i convert this to the
managed abstract basetype?


What about something like this:

__gc class SomeClass
{
UnmanagedObject *pobj;

// ...

public:

UnmanagedObject *GetUnmanagedObject() { return pobj; }

// ...
};
 
J

Jochen Kalmbach [MVP]

Hi WithPit!
I am trying to create an Managed C++ Wrapper around an unmanaged library
which contains C++ code.

Some of the unmanaged methods returns an returntype which is of the abstract
base type (for example unmanagedObject). How can i convert this to the
managed abstract basetype?

If you really write an wrapper then your class should look like:

public __gc Wrapper : public IDisposable
{
public:
Wrapper() {pNative = new NativeClass;)
int WrapperFunction1(...) {return pNative->Function1(...);}
void WrapperFunction2(...) {return pNative->Function2(...);}
void Dispose() (delete pNative;);
private:
NativeClass *pNative;
};

(Of course, sometimes you need to do some marshalling...)

And now, if it returns the object itself, you just need to create an new
instance of the Wrapper-class (and you also must be sure to call the
correctly deletefuntion):

public __gc Wrapper : public IDisposable
{
public:
Wrapper() {pNative = new NativeClass;)
int WrapperFunction1(...) {return pNative->Function1(...);}
void WrapperFunction2(...) {return pNative->Function2(...);}
void Dispose() (delete pNative;);

// *the following is important!*
Wrapper *Function3 {return new Wrapper(pNative->Function3());}
private:
// *the following is important!*
Wrapper(NativeClass *pRef) {pNative = pRef;}
NativeClass *pNative;
};



--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
T

Tommy Svensson \(InfoGrafix\)

Jochen, great and clear examples! Can you please show how to do marshalling
if function2 were to return the following native/unmanaged type:

class MyClass
{
public:
...
char* myStr;
CPoint myPoint;
int myInt;
...
CPoint getPoint();
}

Also, while at it, from the wrapper, how can you return a .NET String from
say native function4 that actually returns char*, tchar*, w_char* or
whatever?

Thx!!!

/Tommy
 
J

Jochen Kalmbach [MVP]

Hi Tommy!
class MyClass
{
public:
...
char* myStr;
CPoint myPoint;
int myInt;
...
CPoint getPoint();
}

Is this a native class?
Maybe you should implement CPoint as a value-type instad of a class...
Also, while at it, from the wrapper, how can you return a .NET String from
say native function4 that actually returns char*, tchar*, w_char* or
whatever?

..NET only uses System::String as the representation of "strings". This
string is always UNICODE.
To convert from "char", "wchar_t" or "TCHAR" simple return the string or
pass it to the System::String-Constructor:

<code>
System::String *GetString1()
{
char *szString = "Hello world1";
return new System::String(szString);
}
System::String *GetString2()
{
wchar_t *szString = L"Hello world2";
return new System::String(szString);
}
System::String *GetString3()
{
TCHAR *szString = _T("Hello world3");
return new System::String(szString);
}
</code>

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
T

Tommy Svensson \(InfoGrafix\)

Thx for your fast reply and thx for the System::String example!

Ok, maybe MyClass is not native but it's unmanaged and it is the actual
definition of the class, which I can't change... it's inside a third party
dll. Anyhow, I have functions in a dll API that return objects of this type,
so how can I deal with it in for example C#?

I can't do like this, right?

In C#:
""""""
using MyWrapperNS; // Access to a MyWrapper type
using MyWrapperNSInternalNativeNS; //access to MyClass

MyWrapper myW = new MyWrapper();
MyClass myClass = myWrapper.callNativeFunction1();

If not (it doesn't :)), then how do I do?

Thx again Jochen for all help,

/TOmmy
 
J

Jochen Kalmbach [MVP]

Hi Tommy!
Ok, maybe MyClass is not native but it's unmanaged and it is the actual
definition of the class, which I can't change... it's inside a third party
dll. Anyhow, I have functions in a dll API that return objects of this type,
so how can I deal with it in for example C#?

I can't do like this, right?

In C#:
""""""
using MyWrapperNS; // Access to a MyWrapper type
using MyWrapperNSInternalNativeNS; //access to MyClass

You can´t access any unmanaged object (in a good way) from a managed
language.

So for your example it looks like the following:

<code>
#pragma unmanaged
class MyClass
{
public:
char* myStr;
CPoint myPoint;
int myInt;
CPoint getPoint() { return CPoint();}
};
#pragma managed


public __gc class MyClassWrapper : public IDisposable
{
public:
MyClassWrapper()
{
pMyClass = new MyClass();
}
__property System::String *get_MyStr()
{
if (pMyClass == NULL)
throw new System::InvalidOperationException(S"Object already
disposed!");
if (pMyClass->myStr == NULL)
return 0;
return new System::String(pMyClass->myStr);
}

__property int get_MyInt()
{
if (pMyClass == NULL)
throw new System::InvalidOperationException(S"Object already
disposed!");
return pMyClass->myInt;
}

__property System::Drawing::point get_MyPoint()
{
if (pMyClass == NULL)
throw new System::InvalidOperationException(S"Object already
disposed!");
return System::Drawing::point(pMyClass->myPoint.x,
pMyClass->myPoint.y);
}
System::Drawing::point GetPoint()
{
if (pMyClass == NULL)
throw new System::InvalidOperationException(S"Object already
disposed!");
CPoint p = pMyClass->getPoint();
return System::Drawing::point(p.x, p.y);
}
void Dispose()
{
Dispose(true);
}
private:
~MyClassWrapper()
{
Dispose(false);
}
void Dispose(bool disposing)
{
if (pMyClass != NULL)
delete pMyClass;
pMyClass = NULL;
if (disposing == true)
System::GC::SuppressFinalize(this);
}
MyClass *pMyClass;
};
</code>

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
T

Tommy Svensson \(InfoGrafix\)

So for your example it looks like the following:
<code>
#pragma unmanaged


Hey, wait a minute... this "#pragma unmanaged" is specific for C++/CLI
right...? I only have VS 2003 with Managed Extensions for C++... or is this
valid in VS 2003 too?

class MyClass
{
public:
char* myStr;
CPoint myPoint;
int myInt;
CPoint getPoint() { return CPoint();}
};
#pragma managed


Ok, now the definition of MyClass is in the same file as my wrapper but the
fact is that the unmanaged API functions reside in a DLL (or a .lib). How
can I get access to them?

Do I need to derive from IDisposable? What happens if I don't?

Thx!!!
 
J

Jochen Kalmbach [MVP]

Hi Tommy!
Hey, wait a minute... this "#pragma unmanaged" is specific for C++/CLI
right...? I only have VS 2003 with Managed Extensions for C++... or is this
valid in VS 2003 too?

It is also valid in VC2003.
By the way: You do not need to set this pragma! I just wanted to show
that this class really can be an unmanaged or native class!
Ok, now the definition of MyClass is in the same file as my wrapper but the
fact is that the unmanaged API functions reside in a DLL (or a .lib). How
can I get access to them?

Äh... whyt should be the problem?
Include the h-File, and add the LIB to your linker settings.
Do I need to derive from IDisposable? What happens if I don't?

An managed class has a non-deterministic life-time!
If you have references to native resources, then you *should* implement
the "IDisposable" pattern.
There are only two other ways to overcome this:
1. It does not matter if the native-resource will be freed from a
different thread during finalization
2. You do not allocate a native-resource in the cinstructor; instead you
allocate it on every method and destroy it before you leave the method.

--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/
 
G

Guest

Thanx for all the replies but that was not my question. I will explain it a
little bit more.

In my unmanaged library code i had the following three classes with the
following hierarchy

Referenced (class)
Object (abstract class, inheriting from referenced)
Node (class, inheriting from object)

I want to make an managed wrapper for it with the same type of classes. So i
created an managed referenced class, and because this is the base class i
give it the pointer to the unmanaged object referenced.

The object class will be an managed abstract class with no constructor,
because abstract class should not have one. One of the methods of the
unmanaged class is cloneObject which should be implemented by the classes
that are inheriting of the abstract class Node. CloneObject gives as result
an value of the type Object.

So now the problem, i create an managed class Node which implements the
cloneObject method. But how to define the body of this method. Because with
not abstract classes i have created an extra constructor which get the
unmanagedobject en wrapped it. But with an abstract return type this is not
possible.

Hope this gives you more details about my question, and i hope somebody had
an solution for it.

Thanx

WithPit
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top