Jump to content
  • Advertisement
Sign in to follow this  
Subotron

[.net] Managed wrapper for unmanaged class (C++)

This topic is 3961 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've written an unmanaged (OO) C++ library that I now want to access from inside C#. I've started building a wrapper in managed C++ for all classes in my library, and so far everything works fine, but I now have an issue I can't resolve nor find anything on (probably I'm searching wrong, but I tried a lot of things). I'm wrapping a class that has some public data members which are pointers (actually boost::shared_ptr) to other classes in the library. Since these pointers are public, I need to include them in the wrapper so they can be used. The class looks like this: (leaving out irrelevant parts)
class Application
{
public:
	boost::shared_ptr<CLog>		Log;
	boost::shared_ptr<CKernel>	Kernel;
	// And some more pointers

	Application	();
	~Application	();
	void Execute	();
};

Wrapping the constructor/destructor/Execute function was easy enough. However, I'm not sure what to do with the pointers to the other classes, since those classes are unmanaged too. One thing I thought of was to write managed versions of these classes as well, and replace the pointers in my managed Application class with pointers to those newly created managed versions of CLog and CKernel. I'm not sure if this is the best/only way to go though, and it seems like a lot of work. Can anyone tell me how to do this? This is my wrapped class so far:
	public ref class cApp
	{
	private:
		Application* application;

	public:
		cApp()
		{
			application = new Application();
		}

		~cApp()
		{
			delete application;
		}

		void Execute()
		{
			application->Execute();
		}
	};

Thanks a lot in advance for any help!

Share this post


Link to post
Share on other sites
Advertisement
C# doesn't know anything about an unmanaged object addressed by a pointer, and can't do anything with it.

So yes, if you want to be able to interact with the log and kernel objects in c#, you'll need to wrap them up, whether by putting them in their own containers, or giving the application class functions to interact with them.

Share this post


Link to post
Share on other sites
It is still not clear to me how to solve this. Suppose I go with the method of wrapping up the other classes too, how do I represent them in a way that matches the C++ representation?

Right now, calling the Application in C# is very straightforward:

Namespace.Application App = new Namespace.Application();
App.Execute();

Now when I call a Log function, it should ideally look like this:

App.Log.Something();

so I figure, the managed Application class should hold a data member that provides direct access to the unmanaged class. However, in the unmanaged class, the application class has already constructed a Log instance in its own constructor. This means the managed Application class should not create a new instance, but rather take the existing one from the unmanaged class and assign it to the (managed) data member. Is this possible? Is it the right way of thinking?

A small code example would be of great help if possible, its hard to find good material on this subject.

Share this post


Link to post
Share on other sites

public ref class cApp
{
private:
Application* application;
Log^ log;

public:
cApp()
{
application = new Application();
log = gcnew Log(application->Log);
}

~cApp()
{
delete application;
}

void Execute()
{
application->Execute();
}

property Log^ Log
{
Namespace::Log^ get() { return log; }
}
};

public ref class Log
{
private:
CLog *m_Pointer;

internal:
Log(CLog* pointer) { m_Pointer = pointer; }

public:
void Method1() { m_Pointer->Method1(); }

void Method2() { m_Pointer->Method2(); }
};



Incidentally, if you want to take a look at a full-blown project using C++/CLI, head over to our page for SlimDX. Sometimes it's easiest to wrap your head around the syntax when you can actually look at some examples, which seem to be sorely lacking on the internet.

Share this post


Link to post
Share on other sites
Thanks a lot! That's exactly what I needed. I came pretty close myself, but lacked syntactical knowledge. I'm pretty sure I can figure out most of my issues now, but I'll definetly check your page out.

Share this post


Link to post
Share on other sites
Quote:
Original post by Subotron
It is still not clear to me how to solve this. Suppose I go with the method of wrapping up the other classes too, how do I represent them in a way that matches the C++ representation?


You would store references to the managed wrapper versions inside of your app, and you can give those wrappers methods that initialize them... Ah, I think I see what you're asking...


public ref class cApp
{
private:
Application* application;

LogWrapper^ managedLog;
KernelWrapper^ managedKernel;

public:
cApp()
{
application = new Application();

// How do we tell this managed object to
// wrap itself around an unmanaged object,
// when we can't pass unmanaged data to
// its managed interface...
managedLog = gcnew LogWrapper();

// etc...
}

~cApp()
{
delete application;
}

void Execute()
{
application->Execute();
}
};



Is that what you're saying?

(When you are in mixed-mode, surely there is a way to get at LogWrapper's unmanaged members.... I'm curious about this also)

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike.Popoloski
log = gcnew Log(application->Log);


I was going to suggest that, but I wasn't aware that you could pass an unmanaged pointer to a managed constructor. That was informative!

Share this post


Link to post
Share on other sites
Quote:
Original post by smitty1276
Quote:
Original post by Mike.Popoloski
log = gcnew Log(application->Log);


I was going to suggest that, but I wasn't aware that you could pass an unmanaged pointer to a managed constructor. That was informative!


Glad to see I'm not the only one having use for this topic :) thanks for your reply, it's good to see all fingers pointing in the same direction, gives me some confirmation this is a good way to do it :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!