溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++ CLI如何寫托管Scene類

發(fā)布時間:2021-11-29 15:27:26 來源:億速云 閱讀:159 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“C++ CLI如何寫托管Scene類”,在日常操作中,相信很多人在C++ CLI如何寫托管Scene類問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C++ CLI如何寫托管Scene類”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

基本思路是將底層3D部分和上層GUI圖形界面部分大體分離。最原始的做法是寫一個C++的類,然后定義一些接口,然后用C++/CLI寫一個Wrapper,然后用C#進行調(diào)用。這種做法其實不是很好,增加了很大的工作量,而且在寫Wrapper的時候難免有很多重復性的賦值代碼。

第二種思路就是直接用C++/CLI開始寫,將Native部分和Managed部分合并在一塊兒寫。當然C++/CLI有一些限制,不能在托管類里面直接嵌套非托管類,只能有非托管類的指針等等。這個限制帶來的最大的不好是osg::ref_ptr,也就是OpenSceneGraph里面的智能指針無法使用了,因為他是一個類型,不能直接嵌入到托管類里面,所以類似下面的語法是錯誤的:

ref class ManagedClass
{
    osg::ref_ptr node;
}

當然這樣寫是正確的:

ref class ManagedClass
{
    osg::Node* node;
}

但這樣就失去了智能指針的保護,很容易造成內(nèi)存泄露,所以當務之急是需要寫一個智能指針來代替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這些常用類只能重寫以便于調(diào)用。像查找節(jié)點FindNode這種函數(shù):

    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#語言無法使用,因為它不能解析一個智能指針?!蛟S,還有別的方法可以用吧,比如用IntPtr這種,但可能又會脫離了智能指針的保護,變的危險起來。

到此,關于“C++ CLI如何寫托管Scene類”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI