9.2. Run Bytecode Directly

The runtime architecture of PikaPython is shown below. By default, the process of parsing Python scripts into Pika bytecode is executed in the MCU, which allows the MCU to run Python scripts directly, including support for interactive running. Instead, in resource-constrained cases, the process of parsing Python scripts into bytecode can be done earlier at the PC, allowing the Python script to be executed directly instead of parsing it in the MCU, so that the code to parse the Python script can be trimmed out.

By avoiding the use of obj_run() to execute python scripts and running the bytecode directly, the compiler will automatically optimize the Python parsed code and reduce the code size footprint.

_images/1639281281608-011ffd89-5851-47d8-9dca-438ed963f5d4-164649975346225.png

9.2.1. Converting Python to bytecode on PC.

The precompiler rust-msc-latest-win10.exe integrates a bytecode generator that compiles main.py and the .py files imported by main.py (including indirect import) to bytecode when precompiling, and the generated bytecode files are in the pikascript-api folder.

The .py file is generated as a .py.o bytecode file, e.g. main.py generates pikascript-api/main.py.o.

At the same time, all .py.o files are automatically packaged into a library file pikascript-api/pikaModules.py.a, which contains all bytecode files.

To facilitate the loading of the library files in mcu when compiling the firmware, the precompiler also automatically converts the library files to C byte array files pikascript-api/__asset_pikaModules_py_a.c.

/* __asset_pikaModules_py_a.c */
#include "PikaPlatform.h"
/* warning: auto generated file, please do not modify */
PIKA_BYTECODE_ALIGN const unsigned char pikaModules_py_a[] = {
    0x7f, 0x70, 0x79, 0x61, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 
...

9.2.2. Using library file

Library files can be imported using the obj_linkLibrary() API, refer to the automatically generated pikaScriptInit()

PikaObj *pikaScriptInit(void){
...
    __pikaMain = newRootObj("pikaMain", New_PikaMain);
    extern unsigned char pikaModules_py_a[];
    obj_linkLibrary(__pikaMain, pikaModules_py_a);
...
}

After importing a library file, you can import the modules contained in the library file directly inside the python script.

It is also possible to run a module directly as a script, e.g.

obj_runModule(__pikaMain, "main");

9.2.3. Run a single bytecode

Read data from a single bytecode file .py.o and then use the pikaVM_runByteCode() API to just run the single bytecode directly, see the usage of starting from bytecode in g030.

https://github.com/pikastech/pikascript/blob/master/bsp/stm32g030c8/Booter/main.c

Note

  1. The byte code run by the pikaVM_runByteCode() API must be of type const, if the byte code is not const, you need to use pikaVM_runByteCodeInconstant().

  2. If you have already docked the file system, you can use the pikaVM_runByteCodeFile() API to run the .py.o file directly.

  3. pikaVM_runByteCodeInconstant() and pikaVM_runByteCodeFile() require kernel version >=v1.11.7.