examples/usercmodule: Add a sub-package example.
This demonstrates how to add a sub-package in a user c module, as well as how to define the necessary qstrs and enable the feature in the build. This is used by the unix coverage build to test this feature. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
parent
6a8114eee8
commit
5e04521251
|
@ -68,7 +68,7 @@ MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
locals_dict, &example_Timer_locals_dict
|
locals_dict, &example_Timer_locals_dict
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define all properties of the module.
|
// Define all attributes of the module.
|
||||||
// Table entries are key/value pairs of the attribute name (a string)
|
// Table entries are key/value pairs of the attribute name (a string)
|
||||||
// and the MicroPython object reference.
|
// and the MicroPython object reference.
|
||||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
EXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||||
|
|
||||||
# Add all C files to SRC_USERMOD.
|
# Add all C files to SRC_USERMOD.
|
||||||
SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
|
SRC_USERMOD += $(CEXAMPLE_MOD_DIR)/examplemodule.c
|
||||||
|
|
||||||
# We can add our module folder to include paths if needed
|
# We can add our module folder to include paths if needed
|
||||||
# This is not actually needed in this example.
|
# This is not actually needed in this example.
|
||||||
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
|
CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR)
|
||||||
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// See example.cpp for the definition.
|
// See example.cpp for the definition.
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
|
||||||
|
|
||||||
// Define all properties of the module.
|
// Define all attributes of the module.
|
||||||
// Table entries are key/value pairs of the attribute name (a string)
|
// Table entries are key/value pairs of the attribute name (a string)
|
||||||
// and the MicroPython object reference.
|
// and the MicroPython object reference.
|
||||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
This is an example of a user C module that includes subpackages.
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Create an INTERFACE library for our C module.
|
||||||
|
add_library(usermod_subpackage_example INTERFACE)
|
||||||
|
|
||||||
|
# Add our source files to the lib
|
||||||
|
target_sources(usermod_subpackage_example INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the current directory as an include directory.
|
||||||
|
target_include_directories(usermod_subpackage_example INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(usermod_subpackage_example INTERFACE
|
||||||
|
MICROPY_MODULE_BUILTIN_SUBPACKAGES=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link our INTERFACE library to the usermod target.
|
||||||
|
target_link_libraries(usermod INTERFACE usermod_subpackage_example)
|
|
@ -0,0 +1,10 @@
|
||||||
|
SUBPACKAGE_EXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||||
|
|
||||||
|
# Add all C files to SRC_USERMOD.
|
||||||
|
SRC_USERMOD += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/modexamplepackage.c
|
||||||
|
|
||||||
|
# We can add our module folder to include paths if needed
|
||||||
|
# This is not actually needed in this example.
|
||||||
|
CFLAGS_USERMOD += -I$(SUBPACKAGE_EXAMPLE_MOD_DIR) -DMICROPY_MODULE_BUILTIN_SUBPACKAGES=1
|
||||||
|
|
||||||
|
QSTR_DEFS += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/qstrdefsexamplepackage.h
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Include MicroPython API.
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
// Define example_package.foo.bar.f()
|
||||||
|
STATIC mp_obj_t example_package_foo_bar_f(void) {
|
||||||
|
mp_printf(&mp_plat_print, "example_package.foo.bar.f\n");
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_bar_f_obj, example_package_foo_bar_f);
|
||||||
|
|
||||||
|
// Define all attributes of the second-level sub-package (example_package.foo.bar).
|
||||||
|
STATIC const mp_rom_map_elem_t example_package_foo_bar_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo_dot_bar) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_bar_f_obj) },
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(example_package_foo_bar_globals, example_package_foo_bar_globals_table);
|
||||||
|
|
||||||
|
// Define example_package.foo.bar module object.
|
||||||
|
const mp_obj_module_t example_package_foo_bar_user_cmodule = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&example_package_foo_bar_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define example_package.foo.f()
|
||||||
|
STATIC mp_obj_t example_package_foo_f(void) {
|
||||||
|
mp_printf(&mp_plat_print, "example_package.foo.f\n");
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_f_obj, example_package_foo_f);
|
||||||
|
|
||||||
|
// Define all attributes of the first-level sub-package (example_package.foo).
|
||||||
|
STATIC const mp_rom_map_elem_t example_package_foo_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&example_package_foo_bar_user_cmodule) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_f_obj) },
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(example_package_foo_globals, example_package_foo_globals_table);
|
||||||
|
|
||||||
|
// Define example_package.foo module object.
|
||||||
|
const mp_obj_module_t example_package_foo_user_cmodule = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&example_package_foo_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define example_package.f()
|
||||||
|
STATIC mp_obj_t example_package_f(void) {
|
||||||
|
mp_printf(&mp_plat_print, "example_package.f\n");
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_f_obj, example_package_f);
|
||||||
|
|
||||||
|
STATIC mp_obj_t example_package___init__(void) {
|
||||||
|
if (!MP_STATE_VM(example_package_initialised)) {
|
||||||
|
// __init__ for builtins is called each time the module is imported,
|
||||||
|
// so ensure that initialisation only happens once.
|
||||||
|
MP_STATE_VM(example_package_initialised) = true;
|
||||||
|
mp_printf(&mp_plat_print, "example_package.__init__\n");
|
||||||
|
}
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package___init___obj, example_package___init__);
|
||||||
|
|
||||||
|
// The "initialised" state is stored on mp_state so that it is cleared on soft
|
||||||
|
// reset.
|
||||||
|
MP_REGISTER_ROOT_POINTER(int example_package_initialised);
|
||||||
|
|
||||||
|
// Define all attributes of the top-level package (example_package).
|
||||||
|
STATIC const mp_rom_map_elem_t example_package_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_package___init___obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_foo), MP_ROM_PTR(&example_package_foo_user_cmodule) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_f_obj) },
|
||||||
|
};
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(example_package_globals, example_package_globals_table);
|
||||||
|
|
||||||
|
// Define module object.
|
||||||
|
const mp_obj_module_t example_package_user_cmodule = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&example_package_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register the module to make it available in Python.
|
||||||
|
// Note: subpackages should not be registered with MP_REGISTER_MODULE.
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_example_package, example_package_user_cmodule);
|
|
@ -0,0 +1,2 @@
|
||||||
|
Q(example_package.foo)
|
||||||
|
Q(example_package.foo.bar)
|
|
@ -96,3 +96,20 @@ print(returns_NULL())
|
||||||
import frozentest
|
import frozentest
|
||||||
|
|
||||||
print(frozentest.__file__)
|
print(frozentest.__file__)
|
||||||
|
|
||||||
|
# test for builtin sub-packages
|
||||||
|
from example_package.foo import bar
|
||||||
|
|
||||||
|
print(bar)
|
||||||
|
bar.f()
|
||||||
|
import example_package
|
||||||
|
|
||||||
|
print(example_package, example_package.foo, example_package.foo.bar)
|
||||||
|
example_package.f()
|
||||||
|
example_package.foo.f()
|
||||||
|
example_package.foo.bar.f()
|
||||||
|
print(bar == example_package.foo.bar)
|
||||||
|
from example_package.foo import f as foo_f
|
||||||
|
|
||||||
|
foo_f()
|
||||||
|
print(foo_f == example_package.foo.f)
|
||||||
|
|
|
@ -52,13 +52,14 @@ mport
|
||||||
|
|
||||||
builtins micropython _thread _uasyncio
|
builtins micropython _thread _uasyncio
|
||||||
btree cexample cmath cppexample
|
btree cexample cmath cppexample
|
||||||
ffi framebuf gc math
|
example_package ffi framebuf
|
||||||
termios uarray ubinascii ucollections
|
gc math termios uarray
|
||||||
ucryptolib uctypes uerrno uhashlib
|
ubinascii ucollections ucryptolib uctypes
|
||||||
uheapq uio ujson umachine
|
uerrno uhashlib uheapq uio
|
||||||
uos urandom ure uselect
|
ujson umachine uos urandom
|
||||||
usocket ussl ustruct usys
|
ure uselect usocket ussl
|
||||||
utime utimeq uwebsocket uzlib
|
ustruct usys utime utimeq
|
||||||
|
uwebsocket uzlib
|
||||||
ime
|
ime
|
||||||
|
|
||||||
utime utimeq
|
utime utimeq
|
||||||
|
@ -211,3 +212,13 @@ b'bytes 1234\x01'
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
frozentest.py
|
frozentest.py
|
||||||
|
example_package.__init__
|
||||||
|
<module 'example_package.foo.bar'>
|
||||||
|
example_package.foo.bar.f
|
||||||
|
<module 'example_package'> <module 'example_package.foo'> <module 'example_package.foo.bar'>
|
||||||
|
example_package.f
|
||||||
|
example_package.foo.f
|
||||||
|
example_package.foo.bar.f
|
||||||
|
True
|
||||||
|
example_package.foo.f
|
||||||
|
True
|
||||||
|
|
Loading…
Reference in New Issue