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

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

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

    与前面的工程相似,工程LuaTutorial3中,同样加入了三个文件:LuaTutorial3.cpp, Tutorial3.i, tutorial3.lua 。其中LuaTutorial3.cpp的内容基本和LuaTutorial2.cpp雷同,不再赘述。

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

     

    namespace tutorial
    {
        struct Point
        {
            float x;
            float y;
            nocode Point();
            nocode Point(float a, float b);
            nocode Point(const Point& pt);
    
            #{
            Point()
            {}
            Point(float a, float b)
            {
                x = a;
                y = b;
            }
            #}
        };
    
        struct Shape
        {
            abstract float getArea();
            ##        virtual ~Shape() {}
        };
    
        struct Triangle : Shape
        {
            Point m_vertices[#3];
            nocode static Triangle+ New();
            #{
                virtual float getArea()
            {
                return fabs(m_vertices[0].x * m_vertices[1].y
                    + m_vertices[1].x * m_vertices[2].y
                    + m_vertices[2].x * m_vertices[0].y
                    - m_vertices[0].x * m_vertices[2].y
                    - m_vertices[1].x * m_vertices[0].y
                    - m_vertices[2].x * m_vertices[1].y) * 0.5;
            }
            static Triangle* New()
            {
                return new Triangle;
            }
            #}
        };
    
    }


    在这里仍然有struct Point。 引入了基类 struct Shape。其中这一行

    abstract float getArea();

    表示声明一个纯虚函数,相当于C++中的

    virtual float getArea() = 0;

    如果不是纯虚函数,使用关键字virtual代替abstract即可。

    新加入了类型 Triangle

    struct Triangle : Shape

    与C++一样,用 : 表示继承。因idlcpp表示的是接口信息,所以只有公有继承。与C++不同,idlcpp并没有public, protected, private这三个关键字。

    然后是数据成员m_vertices;

    Point m_vertices[#3];

    idlcpp只关心接口的信息,在其语法分析部分,只能看见Point m_vertices[]。数字3需要用插入代码的方式。其中#表示直接连在后面的一个标识符或整数(实际上是由字母,下划线和数字组成的串)将插入到生成的C++头文件对应的位置上。下一行

    nocode static Triangle+ New();

    声明了一个名为New的静态函数,其实现代码就在后续的类型声明内,所以此处用nocode阻止在头文件中生成函数声明,如前所述,idlcpp如果看见了构造函数的声明,会生成静态函数New,所以此时不能出现构造函数的声明,以免名字冲突。对照一下后面实现部分的C++声明

    static Triangle* New()

    这里和C++不一致的地方是用+代替了*,放在函数返回值类型与函数名之间,表示函数内部以new的形式创建了一个对象,返回其指针,外界需要用delete的形式删除它(还有另一种关于引用计数的情况,暂不讨论)。在脚本语言中一般自带垃圾收集机制,脚本语言自动管理内存的分配释放。程序员一般不用关心何时删除对象这样的问题,而在C++中在堆上分配对象的生命期一般由程序员维护。为处理其间的差异,idlcpp在函数声明的返回值类型部分有如下几种形式:

    idlcpp声明

    C++声明

    实现

    typeName

    typeName

    返回值

    typeName &

    typeName&

    返回引用

    typeName *

    typeName*

    返回指针

    typeName +

    typeName*

    返回指针,外界需要delete,或者增加了引用计数,外界需要release

    typeName + []

    typeName*

    返回指针,外界需要delete[]

    例如下面的C++代码:

    int g_a;
    int* getGlobal()
    {
        return &g_a;
    }
    
    int* getNew()
    {
        return new int;
    }
    
    int* getNewArray(int count)
    {
        return new int[count];
    }

    三个函数的返回值类型都是int*,但对于后面两个,分别要用delete 和delete[]释放内存,就语法层面看,从函数的声明不能区分这些情况。只能由程序员根据实际情况进行不同的处理。而在脚本语言中并不希望看到显示的删除对象的调用。所以idlcpp通过语法层面的声明,在生成的元数据代码中进行区分,然后由运行时库(pafcore.dll)进行处理。

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

    //DO NOT EDIT THIS FILE, it is generated by idlcpp
    //http://www.idlcpp.org
    
    #pragma once
    
    #include "./Tutorial3.h"
    namespace tutorial{ struct Triangle; }
    
    namespace tutorial
    {
        struct Point
        {
        public:
    
            float x;
            float y;
     
            Point()
            {}
            Point(float a, float b)
            {
                x = a;
                y = b;
            }
            
        };
    
        struct Shape
        {
        public:
    
            virtual float getArea() = 0 ;
            virtual ~Shape() {}
        };
    
        struct Triangle : public Shape
        {
        public:
    
            Point m_vertices[3];
    
                virtual float getArea()
            {
                return fabs(m_vertices[0].x * m_vertices[1].y
                    + m_vertices[1].x * m_vertices[2].y
                    + m_vertices[2].x * m_vertices[0].y
                    - m_vertices[0].x * m_vertices[2].y
                    - m_vertices[1].x * m_vertices[0].y
                    - m_vertices[2].x * m_vertices[1].y) * 0.5;
            }
            static Triangle* New()
            {
                return new Triangle;
            }
            
        };
    
    }

    内容基本上都是和Tutorial3.i中一一对应的。然后看一下脚本tutorial3.lua的内容:

    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);
    
    print(triangle:getArea()._);

    创建了一个tirangle对象,然后设置数据成员,此处运行时能够检测下标的范围为0至2,如果超出范围将会报错,最后调用其基类Shape中声明的函数getArea(),因为这是虚函数,所以最终会调用到Traingle::getArea()。

    编译运行结果如下图:

  • 相关阅读:
    【DL-2-2】卷积神经网络(CNN)--AlexNet、ZFNet、VGGNet、GoogleNet、ResNet
    Python3 错误和异常-(try/except/else/finally/raise/assert)
    生成器 Generators
    Map,Filter 和 Reduce
    装饰器
    目标检测:介绍及传统方法
    【ML-17-2】MCMC--马尔可夫蒙特卡罗方法(MH和Gibbs)
    如何在JDK1.8中愉快地处理日期和时间
    luogu1447 能量采集
    luogu1775 古代人的难题 打表找规律
  • 原文地址:https://www.cnblogs.com/fdyjfd/p/5352765.html
Copyright © 2011-2022 走看看