6.2. PikaScript C 模块开发流程

    编写一个新的模块,首先需要编写模块接口文件,比如编写一个数学计算模块Math,第一步是编写 Math.pyi。

    6.2.2. 编写类接口

    现在我们可以在 Math.pyi 里面新建类了,比如我们要新建一个 类来实现相关的加法运算,我们就可以在 Math.py 里面添加 Adder 类。

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

    使用 ... 代替 pass 的写法也是合法的,例如:

    1. # Math.pyi
    2. class Addr:
    3. def byInt(self, a:int, b:int)->int:...
    4. def byFloat(self, a:float, b:float)->float:...

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

    python 中类的方法的第一个参数都是 self 这是 python 的语法所要求的。

    我们再向 math.py 里面添加一个 Multiplier 类,用来实现乘法,Multiplier 的写法如下所示:

    1. # Math.pyi
    2. class Multiplier:
    3. def byInt(self, a:int, b:int)->int:
    4. pass
    5. def byFloat(self, a:float, b:float)->float:
    6. pass

    到此类接口就编写完成了。我们在 main.py 中引入 Math 模块,这样 Pika 预编译器就会去预编译 Math 模块了。

    双击运行pika预编译器。

    打开 pikascript-api 文件夹可以发现,我们新编写的模块接口对应的头文件已经可以被预编译出来了。

    _images/image-20220916121454812.png

    发现编译报错了,提示是有四个函数没有找到定义。

    这是正常的,因为我们之前并没有为 Math 模块的类编写实现,下面我们就来编写这些类的实现。

    为了模块管理的方便,我们把实现文件都放在 pikascript-lib 文件夹下,

    _images/image-20220916121548065.png

    在 pikascript-lib 文件夹下,新建一个 Math 文件夹,用来放 Math 模块的实现代码。

    然后在 Math 文件夹下新建 .c 文件,建议用 “模块名_类名.c” 的命名方式为每一个类新建一个 .c 文件,提高代码的清晰性。

    _images/131120619-45ae3520-7b63-434b-8831-5b4d9f900cad.png

    然后我们在这两个 .c 文件里面编写类的方法实现。那么问题来了,我们如何知道应当编写哪些实现呢?

    这个很简单,我们打开 Math_Multiplier.h 和 Math_Adder.h 就可以发现,我们需要编写的实现函数已经被自动声明好了。

    1. /* Math_Multiplier.h */
    2. /* ******************************** */
    3. /* ******************************** */
    4. #ifndef __Math_Multiplier__H
    5. #define __Math_Multiplier__H
    6. #include <stdio.h>
    7. #include <stdlib.h>
    8. #include "PikaObj.h"
    9. PikaObj *New_Math_Multiplier(Args *args);
    10. double Math_Multiplier_byFloat(PikaObj *self, double a, double b);
    11. int Math_Multiplier_byInt(PikaObj *self, int a, int b);
    12. #endif
    1. /* Math_Adder.h */
    2. /* ******************************** */
    3. /* Warning! Don't modify this file! */
    4. /* ******************************** */
    5. #ifndef __Math_Adder__H
    6. #define __Math_Adder__H
    7. #include <stdio.h>
    8. #include <stdlib.h>
    9. #include "PikaObj.h"
    10. PikaObj *New_Math_Adder(Args *args);
    11. double Math_Adder_byFloat(PikaObj *self, double a, double b);
    12. int Math_Adder_byInt(PikaObj *self, int a, int b);
    13. #endif

    然后我们直接在 Math_Adder.c 和 Math_Multipler.c 里面去实现这四个函数就 ok 了。

    1. /* Math_Multipler.c */
    2. #include "pikaScript.h"
    3. double Math_Multiplier_byFloat(PikaObj *self, double a, double b)
    4. {
    5. return a * b;
    6. int Math_Multiplier_byInt(PikaObj *self, int a, int b)
    7. {
    8. return a * b;
    9. }

    6.2.4. 测试一下效果

    我们用下面的 main.py 来测试一下我们新编写的模块

    1. # main.py
    2. import Math
    3. adder = Math.Adder()
    4. muler = Math.Multiplier()
    5. res1 = adder.byInt(1, 2)
    6. print('1 + 2')
    7. print(res1)
    8. res2 = adder.byFloat(2.3, 4.2)
    9. print('2.3 + 4.2')
    10. print(res2)
    11. res3 = muler.byInt(2, 3)
    12. print('2 * 3')
    13. print(res3)
    14. res4 = muler.byFloat(2.3, 44.2)
    15. print('2.3 * 44.2')
    16. print(res4)

    运行的效果如下:

    这说明我们编写的模块工作正常了。

    下面的表格列出了 PikaScript 支持的所有类型声明,以及它们与 C 语言的原生类型的对应关系。

    6.2.6. 发布模块

    出于开源的精神,发布你自己的模块是一件非常酷且激动人心的事情。

    发布模块只需要发布类接口和类实现文件即可。

    比如发布刚刚新编写的 Math 模块,就是发布 Math.pyi 文件和 pikascript-lib/Math 文件夹里的文件。

    _images/image-20220916121755609.png