[.net] C# UI with C++ Scene graph (Updated)

Started by
8 comments, last by Sphet 15 years, 9 months ago
Hello, I am starting from scratch on a new GUI application that will leverage a large C++ code base. I have a collection of objects in a C++ scene graph and I would like to make it available for visualization in a C# ui. It is, of course, a level editor. The scene graph in C++ is an abstract interface:

class CLASS_DECLSPEC IGraphNode
{
public:
	virtual ~IGraphNode() { }

	virtual const char* GetName() const;

private:
	// ...
};


I currently have a testbed with a Managed C++ wrapper like this:

public ref class WrapNode
{
public:
	WrapNode();
	~WrapNode();

private:
	IGraphNode*			node;
};


So when nodes are created in the scene graph from XML, all done in C++, the C# can get the objects, but it gets them as Wrapped Nodes. My problem is how do I managed lifespan between IGraphNodes and WrapNodes? What if an IGraphNode goes out of scope (deleted), how do I delete the corresponding WrapNode()? Can I somehow store a pointer to the WrapNode inside my IGraphNode? Not sure how do that given it is managed. I'm really new to this whole C# thing and would like to make it work, but I am not sure where the line is drawn and how to manage this kind of thing. Any examples, thoughts or musings on this would be great. [Edited by - Sphet on July 18, 2008 3:44:27 PM]
Advertisement
You shouldn't really need to worry about this, as long as your WrapNode class free's it's IGraphNode.

As WrapNode is managed (C#), the .NET garbage collector will delete it when it's no longer any references to it.

Hope this helped, post back if you need.
Quote:Original post by beebs1
You shouldn't really need to worry about this, as long as your WrapNode class free's it's IGraphNode.

As WrapNode is managed (C#), the .NET garbage collector will delete it when it's no longer any references to it.

Hope this helped, post back if you need.


You don't need to worry about it PROVIDED the WrapNode "owns" the IGraphNode, and is the only one who can delete it. If someone else can delete the IGraphNode, then you'll need an alternate solution (smart/shared pointers would probably be the easiest).
Quote:Original post by beebs1
You shouldn't really need to worry about this, as long as your WrapNode class free's it's IGraphNode.

As WrapNode is managed (C#), the .NET garbage collector will delete it when it's no longer any references to it.

Hope this helped, post back if you need.



Well, that's my question.

If I have a WrapNode that internally poitns to an IGraphNode, how do I remove the reference to the WrapNode if the IGraphNode is deleted, but from within the C++ code?
Quote:Original post by emeyex
Quote:Original post by beebs1
You shouldn't really need to worry about this, as long as your WrapNode class free's it's IGraphNode.

As WrapNode is managed (C#), the .NET garbage collector will delete it when it's no longer any references to it.

Hope this helped, post back if you need.


You don't need to worry about it PROVIDED the WrapNode "owns" the IGraphNode, and is the only one who can delete it. If someone else can delete the IGraphNode, then you'll need an alternate solution (smart/shared pointers would probably be the easiest).


Thanks - that's a good answer. Unfortunately, I have to assume that the WrapNode does NOT own the object, at least, I think I do.

I can't imagine getting away with the C++ code not destroying nodes.

Maybe my over-all architecture will work out if I do more design work, but I just don't see how to do it given that the scene graph is in C++ but I want to be able to extract properties from nodes and edit them in C#, show the selection set, etc.

I guess I could make some kind of scene-graph-iterator which can be used by C# to walk the current selection set, or the whole tree, or what have you and can be invalidated if an object is added or removed from the scene.

Here is my breakdown:

C++: Scene Graph, Scene Object Plugins ( entities, physics, lights ), Serialization, Rendering, property server, Hit Testing, Transform Modification, drag-to-parent, drag-to-link, drag-to-signal/slot
C#: Menus, docking window swith information, representation of scenegraph, buttons to create/destroy objects, Scene Object property views (plug-able).

so in there I need an interface in managed C++, or maybe Swig, whichever is easiest I guess.


S


Do you "have" to use C#? Others' experiences may be different, but I've found that it can be a real pain (especially for maintenance) to wrap a large C++ code base and expose it to C#... requires lots of essentially duplicated glue code. I'm personally a bigger fan of using a C++-based gui toolkit (I'm using wxWidgets) to do my GUI work, so that I don't need an extra glue layer... It all depends though on how you go about it, if you can keep your points-of-contact between C# and C++ few, then it shouldn't be too bad to write a managed CLI wrapper for your C++.

That said, I love C#, and it's great for GUIs... so if you can find a good way to make it work, all the better.
Quote:Original post by emeyex
Do you "have" to use C#? Others' experiences may be different, but I've found that it can be a real pain (especially for maintenance) to wrap a large C++ code base and expose it to C#... requires lots of essentially duplicated glue code. I'm personally a bigger fan of using a C++-based gui toolkit (I'm using wxWidgets) to do my GUI work, so that I don't need an extra glue layer... It all depends though on how you go about it, if you can keep your points-of-contact between C# and C++ few, then it shouldn't be too bad to write a managed CLI wrapper for your C++.

That said, I love C#, and it's great for GUIs... so if you can find a good way to make it work, all the better.


I appreciate your ideas and to be honest, were I the only one in using the codebase, I would write the whole thing in C++ using MFC.

Unfortunately, people already feel stopping game programming to write UI code is a big enough pain, so I am trying to lower the barrier of entry by using C# and a couple of UI frameworks out there. Our goal is to develop the toolset into a framework so game-programmers can essentially write simple plugins either to the scenegraph or to the UI components, depending on what they need to do.

It's a good point though.
You cannot really remove the WrapNode, but you could set its state to deleted or something as soon as IGraphNode's destructor is called. And yes, you can have managed members in an unmanaged type:

#include <vcclr.h>ref class MyManagedClass;class MyUnmanagedClass{gcroot<MyManagedClass^> myManagedObject; // Same behavior as a simple MyManagedClass^.};
Quote:Original post by Expandable
You cannot really remove the WrapNode, but you could set its state to deleted or something as soon as IGraphNode's destructor is called. And yes, you can have managed members in an unmanaged type:

#include <vcclr.h>ref class MyManagedClass;class MyUnmanagedClass{gcroot<MyManagedClass^> myManagedObject; // Same behavior as a simple MyManagedClass^.};



Thanks for that. I think I'll spend the day trying out some samples and seeing what works. I'll post my findings here.
So,

I've done some testing and some thinking and I believe the right way to go is this:

- Write my scene graph in CLI/C++ (I think).
- Each node in the scene graph (ISceneNode) hold a pointer to the object at that node in the graph (ISceneObject), defined in CLI/C++.
- A concrete implementation of ISceneObject in the CLI/C++ and is essentially a container for native objects (SceneModelObject, SceneLightObject).
- Additionally, concrete implementations of ISceneObject can be created in C# for trivial objects, whereby their OnRenderObject() function uses a CLI/C++ ISimpleRenderer for rendering lines and boxes and such using the native C++ renderer.

All properties will be managed using C# or CLI/C++ properties employing the TypeDescriptionProvider/CustomTypeDescriptor classes for publishing.

Hit testing will be done in C# but ISceneObjects can implement their hit testing in either C#, CLI/C++ or native C++.

Right now my Assembly Dependency looks like this:

C# -> CLI/C++ -> C++

If I define a class in C# that is needed in CLI/C++, which in turn defines classes needed in C#, how do you avoid the circular references?

Thoughts??

This topic is closed to new replies.

Advertisement