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
|
||||
);
|
||||
|
||||
// Define all properties of the module.
|
||||
// Define all attributes of the module.
|
||||
// Table entries are key/value pairs of the attribute name (a string)
|
||||
// and the MicroPython object reference.
|
||||
// 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.
|
||||
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
|
||||
# This is not actually needed in this example.
|
||||
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
|
||||
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR)
|
||||
|
@ -4,7 +4,7 @@
|
||||
// See example.cpp for the definition.
|
||||
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)
|
||||
// and the MicroPython object reference.
|
||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||
|
1
examples/usercmodule/subpackage/README.md
Normal file
1
examples/usercmodule/subpackage/README.md
Normal file
@ -0,0 +1 @@
|
||||
This is an example of a user C module that includes subpackages.
|
19
examples/usercmodule/subpackage/micropython.cmake
Normal file
19
examples/usercmodule/subpackage/micropython.cmake
Normal file
@ -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)
|
10
examples/usercmodule/subpackage/micropython.mk
Normal file
10
examples/usercmodule/subpackage/micropython.mk
Normal file
@ -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
|
84
examples/usercmodule/subpackage/modexamplepackage.c
Normal file
84
examples/usercmodule/subpackage/modexamplepackage.c
Normal file
@ -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);
|
2
examples/usercmodule/subpackage/qstrdefsexamplepackage.h
Normal file
2
examples/usercmodule/subpackage/qstrdefsexamplepackage.h
Normal file
@ -0,0 +1,2 @@
|
||||
Q(example_package.foo)
|
||||
Q(example_package.foo.bar)
|
@ -96,3 +96,20 @@ print(returns_NULL())
|
||||
import frozentest
|
||||
|
||||
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
|
||||
btree cexample cmath cppexample
|
||||
ffi framebuf gc math
|
||||
termios uarray ubinascii ucollections
|
||||
ucryptolib uctypes uerrno uhashlib
|
||||
uheapq uio ujson umachine
|
||||
uos urandom ure uselect
|
||||
usocket ussl ustruct usys
|
||||
utime utimeq uwebsocket uzlib
|
||||
example_package ffi framebuf
|
||||
gc math termios uarray
|
||||
ubinascii ucollections ucryptolib uctypes
|
||||
uerrno uhashlib uheapq uio
|
||||
ujson umachine uos urandom
|
||||
ure uselect usocket ussl
|
||||
ustruct usys utime utimeq
|
||||
uwebsocket uzlib
|
||||
ime
|
||||
|
||||
utime utimeq
|
||||
@ -211,3 +212,13 @@ b'bytes 1234\x01'
|
||||
2
|
||||
3
|
||||
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
Block a user