您好,登錄后才能下訂單哦!
這篇文章主要介紹“C++ CLI如何寫托管Scene類”,在日常操作中,相信很多人在C++ CLI如何寫托管Scene類問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C++ CLI如何寫托管Scene類”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
基本思路是將底層3D部分和上層GUI圖形界面部分大體分離。最原始的做法是寫一個C++的類,然后定義一些接口,然后用C++/CLI寫一個Wrapper,然后用C#進行調用。這種做法其實不是很好,增加了很大的工作量,而且在寫Wrapper的時候難免有很多重復性的賦值代碼。
第二種思路就是直接用C++/CLI開始寫,將Native部分和Managed部分合并在一塊兒寫。當然C++/CLI有一些限制,不能在托管類里面直接嵌套非托管類,只能有非托管類的指針等等。這個限制帶來的最大的不好是osg::ref_ptr,也就是OpenSceneGraph里面的智能指針無法使用了,因為他是一個類型,不能直接嵌入到托管類里面,所以類似下面的語法是錯誤的:
ref class ManagedClass { osg::ref_ptr node; }
當然這樣寫是正確的:
ref class ManagedClass { osg::Node* node; }
但這樣就失去了智能指針的保護,很容易造成內存泄露,所以當務之急是需要寫一個智能指針來代替osg::ref_ptr,但基本上要保持功能的不變。OpenSceneGraph的引用類都是繼承與osg::Object,而osg::Object又是繼承于osg::Reference。所以這些引用類都有ref()和unref()方法,用于增加和減少ReferenceCount,當ReferenceCount=0時,就自動delete了。
參考osg::ref_ptr并去掉這個類中不常用的部分,寫了一個smart_ptr類,完成了智能指針的任務:
//! OpenSceneGraph managed smart_ptr. template public ref class smart_ptr { public: typedef T element_type; smart_ptr() : _ptr(0) {} smart_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); } smart_ptr(const smart_ptr% rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); } ~smart_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; } smart_ptr% operator = (const smart_ptr% rp) { if (_ptr==rp._ptr) return *this; T* tmp_ptr = _ptr; _ptr = rp._ptr; if (_ptr) _ptr->ref(); // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); return *this; } inline smart_ptr% operator = (T* ptr) { if (_ptr==ptr) return *this; T* tmp_ptr = _ptr; _ptr = ptr; if (_ptr) _ptr->ref(); // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); return *this; } //T% operator*() { return *_ptr; } T* operator->() { return _ptr; } T* get() { return _ptr; } bool operator!() { return _ptr==0; } // not required bool valid() { return _ptr!=0; } T* release() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp; } private: T* _ptr; };
如此這般折騰以后,終于可以在托管類中間使用智能指針了:
public ref class Scene { protected: smart_ptr gc; smart_ptr root; smart_ptr viewer; smart_ptr camera; ....
跨越了智能指針的障礙以后,還有很多問題有待于解決。像osg::Vec3這些常用類只能重寫以便于調用。像查找節點FindNode這種函數:
ref class NodeFound { public: String^ name; smart_ptr osgNode; }; NodeFound^ FindNode(String^ name) { FindNodeVisitor findNodeVisitor; findNodeVisitor.name=MarshalString(name); root->accept(findNodeVisitor); if(findNodeVisitor.node==NULL) throw gcnew Exceptions::NodeNotFoundExpection(); NodeFound^ nodeFound=gcnew NodeFound(); nodeFound->name=name; nodeFound->osgNode=findNodeVisitor.node; return nodeFound; return nullptr; }
只能定義一個新的結構作為返回值,否則C#語言無法使用,因為它不能解析一個智能指針。……或許,還有別的方法可以用吧,比如用IntPtr這種,但可能又會脫離了智能指針的保護,變的危險起來。
到此,關于“C++ CLI如何寫托管Scene類”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。