microPython的源码解析之 objarray.c

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.

microPython Python最小内核源码解析
这段代码是MicroPython的内部实现,涉及数组(array)、字节数组(bytearray)和内存视图(memoryview)对象的创建、操作和管理。代码中包含了对象的构造函数、打印函数、迭代器、索引操作、缓冲区获取等方法的实现。这些方法为MicroPython提供了强大的数据结构和内存管理能力,使得在资源受限的微控制器上也能进行高效的数据处理。

#include <string.h>
#include <assert.h>
#include <stdint.h>

#include "py/runtime.h"
#include "py/binary.h"
#include "py/objstr.h"
#include "py/objarray.h"

// 判断是否支持某些MicroPython内置模块
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW

// 关于memoryview对象:我们希望尽可能重用array的代码,并保持memoryview对象的大小为4个词,以便它适合1个GC块。
// 此外,memoryview必须保留指向缓冲区基础的指针,以便如果原始父对象不再存在,缓冲区不会被GC回收(我们假设所有可memoryview的对象都返回指向GC块开头的指针)。
// 鉴于上述限制,我们进行以下操作:
//  - 如果缓冲区是读写的,则设置typecode高位(否则为只读)
//  - free是memoryview中第一个元素的偏移量
//  - len是元素长度
//  - items指向原始缓冲区的开始
// 请注意,我们不处理原始缓冲区可能由于原始父对象的大小调整而改变大小的情况。

// 如果启用了memoryview,则定义TYPECODE_MASK
#define TYPECODE_MASK (0x7f)
// memview_offset是memoryview中第一个元素的偏移量
#define memview_offset free
// memview_offset_max是memview_offset的最大值
#define memview_offset_max ((1LL << MP_OBJ_ARRAY_FREE_SIZE_BITS) - 1)
#else
// 如果没有启用memoryview,则使(& TYPECODE_MASK)成为一个空操作以捕获错误
#define TYPECODE_MASK (~(size_t)0)
// 如果没有启用memoryview,则不应访问memview_offset,因此不定义以捕获错误
#endif

// 声明函数
static mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);
static mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
static mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);
static mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);

/******************************************************************************/
// array对象的实现

// 如果启用了bytearray或array模块
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
// 打印array对象
static void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
   
    // kind参数被忽略
    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
    // 根据typecode打印不同的信息
    if (o->typecode == BYTEARRAY_TYPECODE) {
   
        mp_print_str(print, "bytearray(b");
        mp_str_print_quoted(print, o->items, o->len, true);
    } else {
   
        mp_printf(print, "array('%c'", o->typecode);
        if (o->len > 0) {
   
            mp_print_str(print, ", [");
            for (size_t i = 0; i < o->len; i++) {
   
                if (i > 0) {
   
                    mp_print_str(print, ", ");
                }
                // 使用typecode打印元素
                mp_obj_print_helper(print, mp_binary_get_val_array(o->typecode, o->items, i), PRINT_REPR);
            }
            mp_print_str(print, "]");
        }
    }
    mp_print_str(print, ")");
}
#endif

// 如果启用了bytearray或array模块
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
// 创建新的array对象
static mp_obj_array_t *array_new(char typecode, size_t n) {
   
    // 根据typecode计算每个元素的大小
    int typecode_size = mp_binary_get_size('@', typecode, NULL);
    mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
    // 根据typecode设置对象类型
    #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
    o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
    #elif MICROPY_PY_BUILTINS_BYTEARRAY
    o->base.type = &mp_type_bytearray;
    #else
    o->base.type = &mp_type_array;
    #endif
    o->typecode = typecode;
    o->free = 0; // 初始化free为0
    o->len = n; // 设置元素数量
    // 分配内存存储元素
    o->items = m_new(byte, typecode_size * o->len);
    return o;
}
#endif

// 如果启用了bytearray或array模块
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
// 根据给定对象构造array对象
static mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
   
    // 如果是bytearray,可以从任何支持缓冲协议的对象中初始化
    // 其他数组只能从bytes和bytearray对象中初始化
    mp_buffer_info_t bufinfo;
    // 检查是否可以从缓冲区中读取数据
    if (((MICROPY_PY_BUILTINS_BYTEARRAY
          && typecode == BYTEARRAY_TYPECODE)
         || (MICROPY_PY_ARRAY
             && (mp_obj_is_type(initializer, &mp_type_bytes)
                 || (MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(initializer, &mp_type_bytearray)))))
        && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {
   
        // 从原始字节构造数组
        // 向下取整len以使其成为sz的倍数(CPython会抛出错误)
        size_t sz = mp_binary_get_size('@', typecode, NULL);
        size_t len = bufinfo.len 
  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值