pikapython/doc/3.PikaScript标准开发流程.md

7.3 KiB
Raw Blame History

3.Pikascript标准开发流程

本篇文档将会介绍基于PikaScript开发的标准流程这个标准流程将会涵盖大部分情况下会用到的PikaScript相关技术。

我们依然以keil的仿真工程为例如果还没有获得仿真工程请参考1.三分钟快速上手

(1). 使用已有的PikaScript类包

a) PikaScript类包与包接口

我们打开pikascript文件夹发现文件夹根目录下除了main.py还有Device.pyPikaObj.py和PikaStdLib.py这三个.py文件分别对应三个PikaScript类包(class package),简称(package),每个.py文件本身称为包接口(package interface)。一个类包中可以包含若干个相关性较强的类。

image

每一个PikaScript类包包接口包实现(package implement)两部分组成。

我们先打开Device.py查看一下内容在后续的文档中我们会称Device.py为Device包接口

以下就是Device.py的全部内容。

# Device.py
from PikaObj import *

class LED(TinyObj):
    def on():
        pass
    def off():
        pass

class Uart(TinyObj):
    def send(data:str):
        pass
    def setName(name:str):
        pass
    def printName():
        pass

可以看到Device.py中使用pyhon标准语法定义了两个类分别是LED类和Uart类,这两个类都继承自TinyObj

LED类中定义了两个方法分别是on()方法和off()方法,而Uart类则定义了send(data:str)方法、setName(name:str)方法和printName()方法。

可以看到,这些方法都有一个特点,与其说这是方法的定义,不如说是方法的声明因为所有的方法实现都pass掉了都没有写实现。而且方法的入口参数都是带有类型声明的。比如data:str就表示一个data参数,参数类型为str即字符串类型。

这是因为这个包的包实现是由C语言编写的也就是说PikaScript的所有类包都是使用python语法编写声明而使用C语言编写实现。PikaScript的类包开发是一种面向接口编程的混合编程技术。

然而在使用已有的类包时,是不需要了解包实现的,只需要了解包接口,即可使用这个类包。

b) 导入并调用包

下面我们看一下如何使用这个类包。

我们打开工程中的main.py见名知意这个文件是PikaScript的入口文件。

main.py的内容如下

# main.py
from PikaObj import  *
import Device
import PikaStdLib 

led = Device.LED()
uart = Device.Uart()
mem = PikaStdLib.MemChecker()

print('hello wrold')
uart.setName('com1')
uart.send('My name is:')
uart.printName()
print('mem used max:')
mem.max()
print('mem used now:')
mem.now()

导入一个已经编写好的类包是非常简单的比如导入Device包只需要import Device即可,要注意的是所有的.py文件应当放在pikascript文件架的根目录下。

然后使用Device中的LED类新建对象只需要写一句uart = Device.Uart()即可,这表示新建一个uart对象这个对象的类是Device包中的Uart类。

调用方法则使用uart.setName('com')这种形式这都是Python的标准语法不需要过多介绍。

在main.py中写好包的调用后双击rust-msc-v0.5.0.exe即可预编译PikaScript工程预编译的输出文件在pikascrip-api文件夹内。

image

pika预编译器会为导入的包生成.h声明文件和-api.c构造器文件。文件名以包名开头每个类对应一个.h文件和一个-api.c文件。

image

而PikaMain-api.c和PikaMain.h则是对应了一个特殊的类这个类是PikaScript的主类由main.py编译而成。

image

pikaScript.c和pikaScript.h则是根据main.py编译出的初始化函数运行初始化函数时会自动执行启动脚本。

image

在现在的main.py中启动脚本是写在最外层的方法调用也就是:

print('hello wrold')
uart.setName('com1')
uart.send('My name is:')
uart.printName()
print('mem used max:')
mem.max()
print('mem used now:')
mem.now()

编译出的pikaScriptInit()初始化函数对应的是:

PikaObj * pikaScriptInit(){
    PikaObj * pikaMain = newRootObj("pikaMain", New_PikaMain);
    obj_run(pikaMain, "print('hello wrold')");
    obj_run(pikaMain, "uart.setName('com1')");
    obj_run(pikaMain, "uart.send('My name is:')");
    obj_run(pikaMain, "uart.printName()");
    obj_run(pikaMain, "print('mem used max:')");
    obj_run(pikaMain, "mem.max()");
    obj_run(pikaMain, "print('mem used now:')");
    obj_run(pikaMain, "mem.now()");
    return pikaMain;
}

(2) 编写新的PikaScript类包

a)编写包接口

编写一个新的类包首先需要编写包接口文件比如编写一个数学计算类包Math第一步是编写Math.py包名首字母应当大写。

如果要从PikaScript基本类中创建新的类则需要import PikaObj类包import PikaObj类包应使用from PikaObj import *的引入方式。

# Math.py
from PikaObj import *

我们可以打开PikaObj.py文件查看里面的类接口

class TinyObj:
    pass
class BaseObj(TinyObj):
    pass
def print(val: any):
    pass
def set(argPath: str, val: any):
    pass

可以看到里面有TinyObjBaseObj两个类这两个类是由PikaScript内核实现的基本类TinyObj是没有任何功能的最基本的类内存占用最少BaseObjTinyObj相似,但是BaseObj可以挂载子对象。

print(val: any)表示输入参数为泛型的函数,set(argPath:str, val:any)也是泛型函数这两个函数由内核实现PikaScript类包目前还不支持自定义泛型函数。

b)新建一个类

现在我们可以在Math.py里面新建类了比如我们要新建一个Adder类来实现相关的加法运算我们就可以在Math.py里面添加Adder类为了节省内存Adder类从TinyObj基类中继承。

然后我们希望Adder可以为整形、浮点型数据提供加法运算那么就可以添加addInt方法和addFloat方法。

# Math.py
class Adder(TinyObj):
    byInt(a:int, b:int)->int:
    pass
    byFloat(a:float, b:float)->float:
    pass

上面的一段代码中我们定义了Adder类,并添加了两个方法的声明,byInt(a:int,b:int)->int表示方法名为byInt,输入参数为abab的类型都是int型,而返回值也是int型,返回值由->int来确定这都是python的标准语法是带类型声明的写法。

我们再向math.py里面添加一个Multiplier类用来实现乘法Multiplier的写法如下所示Multiplier类同样从TinyObj基类中继承:

# Math.py
class Multiplier(TinyObj):
    byInt(a:int, b:int)->int:
    pass
    byFloat(a:float, b:float)->float:
    pass