zoukankan      html  css  js  c++  java
  • C++混合编程之idlcpp教程Lua篇(7)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(6)

    第一篇在这 C++混合编程之idlcpp教程(一)

    与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件:LuaTutorial5.cpp, Tutorial5.cpp, Tutorial5.i, tutorial5.lua。其中LuaTutorial5.cpp的内容基本和LuaTutorial4.cpp雷同,不再赘述。

    首先看一下Tutorial5.i的内容:

    #import "../../paf/src/pafcore/Reference.i"
    ###include <vector>
    
    namespace tutorial
    {
        struct Point
        {
            float x;
            float y;
            Point();
            Point(float a, float b);
            nocode Point(const Point& pt);
        };
    
        override class Shape : Reference
        {
            override abstract float getArea();
            ##        virtual ~Shape() {}
        };
    
        class ShapeManager(value_object)
        {
            void addShape(Shape* shape);
            float getTotalArea();
            static ShapeManager* GetInstance();
            #{
            ~ShapeManager();
        private:
            std::vector<Shape*> m_shapes;
            #}
        };
    
    
        class Triangle : Shape
        {
            Point m_vertices[#3];
            nocode Triangle();
            ##virtual float getArea();
        };
    
    }

    与Tutorial4.i相比,大部分内容是一样的,不同之处在于类型Shape的声明以及其下的纯虚函数getArea;

    override class Shape : Reference

    override abstract float getArea();

    在这两处声明的最前面都多了一个关键字override。法意味着可以在脚本代码中写一个类型,让它“派生”自Shape,并且能够“重写”虚函数getArea。当然实际上是通过idlcpp生成的一个派生类配合脚本插件代码来完成类似的任务。通过在类型的声明class 前加上关键字override表示此类型可以被脚本“派生”,在虚函数声明的关键字virtual 或 abstract前加上关键字override表示此虚函数可以被脚本“重写”。

    在宿主语言和脚本的混合使用中,一个常见的用法是在宿主语言中根据一定的条件向外发出事件,而用脚本语言来编写事件处理代码,例如在WOW中用一个XML文件描述GUI界面,同时注明事件处理函数对应的Lua函数名。idlcpp提供的脚本继承C++类然后重写虚函数的功能可以很好的实现类似的需求。

    编译后生成的Tutorial5.h的内容如下:

    //DO NOT EDIT THIS FILE, it is generated by idlcpp
    //http://www.idlcpp.org
    
    #pragma once
    
    #include "../../paf/src/pafcore/Typedef.h"
    #include "../../paf/src/pafcore/Reference.h"
    #include <vector>
    
    namespace tutorial
    {
        struct Point
        {
        public:
    
            float x;
            float y;
            Point();
            Point(float a,float b);
        };
    
        class Shape : public pafcore::Reference
        {
        public:
            static ::pafcore::ClassType* GetType();
            virtual ::pafcore::ClassType* getType();
            virtual size_t getAddress();
    
            virtual float getArea() = 0 ;
            virtual ~Shape() {}
        };
    
        class ShapeManager
        {
        public:
    
            void addShape(Shape* shape);
            float getTotalArea();
            static ShapeManager* GetInstance();
    
            ~ShapeManager();
        private:
            std::vector<Shape*> m_shapes;
            
        };
    
    
        class Triangle : public Shape
        {
        public:
            static ::pafcore::ClassType* GetType();
            virtual ::pafcore::ClassType* getType();
            virtual size_t getAddress();
    
            Point m_vertices[3];
    virtual float getArea();
        };
    
    }

    这里生成的代码和Tutorial4.h基本一致。

    最后看一下Tutorial5.lua的内容

    Circle = {}
    Circle.__index = Circle;
    
    function Circle.New()
        circle= {radius = 1.0}
        setmetatable(circle, Circle);
        circle.shape = paf.tutorial.Shape._Derive_(circle);
        return circle;
    end
    
    function Circle:getArea()
        return self.radius * self.radius * 3.1415926;
    end
    
    circle = Circle.New();
    circle.radius = 2.0;
    shapeManager = paf.tutorial.ShapeManager.GetInstance();
    shapeManager:addShape(circle.shape);
    print(shapeManager:getTotalArea()._);
    
    triangle = paf.tutorial.Triangle();
    triangle.m_vertices[0] = paf.tutorial.Point(0,0);
    triangle.m_vertices[1] = paf.tutorial.Point(0,1);
    triangle.m_vertices[2] = paf.tutorial.Point(1,1);
    shapeManager:addShape(triangle);
    print(shapeManager:getTotalArea()._);

    在上面的代码中,写了一个类型Circle。在函数Circle.New 通过下面这一行

    circle.shape = paf.tutorial.Shape._Derive_(circle);

    来模拟继承,语法:C++类型._Derive_(脚本对象) 用于完成模拟继承的行为。实际上circle.shape才是C++类型Shape的派生类实例的引用,在C++中需要用到Shape类型的地方,将circle.shape传递过去即可,如下面的使用方式。

    shapeManager:addShape(circle.shape);

    然后在类型Circle中提供一个与C++基类同名的函数getArea用来计数圆的面积即可,最终使用时脚本插件会找到对应函数进行调用。

    编译执行,结果如下图:

  • 相关阅读:
    DataTable四个方法
    c++面向对象编程必备“良方”(转)
    函数调用约定
    AFX_IDW_PANE_FIRST(转)
    CString.Format的详细用法(转)
    ID的分配 (转)
    CString用法整理(转载)
    jquery之效果
    JS 水仙数
    CSS 文本换行
  • 原文地址:https://www.cnblogs.com/fdyjfd/p/5402962.html
Copyright © 2011-2022 走看看