OpenSceneGraph 筆記–C++/CLI寫託管Scene類

來源:互聯網
上載者:User
最近學了C++/CLI,也寫了一些小玩意兒體驗了它的強大,昨天開始籌劃將以前的彎管機的類比程式用C++/CLI重寫。
基本思路是將底層3D部分和上層GUI圖形介面部分大體分離。最原始的做法是寫一個C++的類,然後定義一些介面,然後用C++/CLI寫一個
Wrapper,然後用C#進行調用。這種做法其實不是很好,增加了很大的工作量,而且在寫Wrapper的時候難免有很多重複性的賦值代碼。
第二種思路就是直接用C++/CLI開始寫,將Native部分和Managed部分合并在一塊兒寫。當然C++/CLI有一些限制,不能在託管類裡面直
接嵌套非託管類,只能有非託管類的指標等等。這個限制帶來的最大的不好是osg::ref_ptr,也就是OpenSceneGraph裡面的智能指標無
法使用了,因為他是一個類型,不能直接嵌入到託管類裡面,所以類似下面的文法是錯誤的:
ref class ManagedClass
{
  osg::ref_ptr<osg::Node> 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<typename T>
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<osg::GraphicsContext> gc;
        smart_ptr<osg::Group> root;
        smart_ptr<osgViewer::Viewer> viewer;
        smart_ptr<osg::Camera> camera;
.
}

跨越了智能指標的障礙以後,還有很多問題有待於解決。像osg::Vec3這些常用類只能重寫以便於調用。像尋找節點FindNode這種函數:        ref class NodeFound
        {
        public:
            String^ name;
            smart_ptr<osg::Node> 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這種,但可能又會脫離了智能指標的保護,變的危險起來。
繼續學習中~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.