Output
\n\n```c\n// Include required definitions first.\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n\n//Adds two integers\n//:param a:\n//:param b:\n//:return:a + b\nSTATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {\n mp_int_t a = mp_obj_get_int(a_obj);\n mp_int_t b = mp_obj_get_int(b_obj);\n mp_int_t ret_val;\n\n //Your code here\n\n return mp_obj_new_int(ret_val);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);\n\nSTATIC const mp_rom_map_elem_t example_module_globals_table[] = {\n\t{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) },\n\t{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);\nconst mp_obj_module_t example_user_cmodule = {\n\t.base = {&mp_type_module},\n\t.globals = (mp_obj_dict_t*)&example_module_globals,\n};\n\nMP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED);\n```\n
\n\nThis will parse all the functions in the module and attach them to the same namespace in micropython.\n##### Note: It will only generate the boilerplate code and not the actual code that does the work such as a + b\nAfter editing the code in the template at the place marked //Code goes here you can follow the instructions \n[here](http://docs.micropython.org/en/latest/develop/cmodules.html#basic-example) for modifying \nthe Make File and building the module into your micro python deployment.\n\nYou should then be able to use the module in micro python by typing\n```python\nimport example # from example.c compiled into micropython\nexample.add_ints(1, 2)\n# prints 3\n```\n##### Note: This example.py is the one compiled into the micropython source and not the file we created earlier\n\n### Advanced usage\nIf you added two more functions to the original example.py\n```python\ndef lots_of_parameters(a: int, b: float, c: tuple, d: object, e: str) -> None:\n \"\"\"\n :param a:\n :param b:\n :param c:\n :param d:\n :return:\n \"\"\"\n\ndef readfrom_mem(addr: int = 0, memaddr: int = 0, arg: object = None, *, addrsize: int = 8) -> str:\n \"\"\"\n :param addr:\n :param memaddr:\n :param arg:\n :param addrsize: Keyword only arg\n :return:\n \"\"\"\n```\n\nlogs_of_parameters shows the types of types you can parse in. You always need to annotate each parameter and the return.\nreadfrom_mem shows that you can set default values for certain parameters and specify that addrsize is a keyword only\nargument.\n\nAt the c level in micropython, there is only three ways of implementing a function.\n##### Basic Case\n```python\ndef foo(a, b, c): # 0 to 3 args\n pass\n```\n```c\nMP_DEFINE_CONST_FUN_OBJ_X // Where x is 0 to 3 args\n```\n##### Greater than three positional args\n```python\ndef foo(*args):\n pass\n```\n```c\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN\n```\n##### Arbitary args\n```python\ndef foo(*args, **kwargs):\n pass\n```\n```c\nMP_DEFINE_CONST_FUN_OBJ_KW\n```\nEach successively increasing the boiler plate to conveniently accessing the variables.\nUsing the same code to parse it\n```python\nimport ustubby\nimport example\n\nprint(ustubby.stub_module(example))\n```\nOutput
\n\n```c\n// Include required definitions first.\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n\n//Adds two integers\n//:param a:\n//:param b:\n//:return:a + b\nSTATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {\n mp_int_t a = mp_obj_get_int(a_obj);\n mp_int_t b = mp_obj_get_int(b_obj);\n mp_int_t ret_val;\n\n //Your code here\n\n return mp_obj_new_int(ret_val);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);\n//\n//:param a:\n//:param b:\n//:param c:\n//:param d:\n//:return:\n//\nSTATIC mp_obj_t example_lots_of_parameters(size_t n_args, const mp_obj_t *args) {\n mp_int_t a = mp_obj_get_int(a_obj);\n mp_float_t b = mp_obj_get_float(b_obj);\n mp_obj_t *c = NULL;\n size_t c_len = 0;\n mp_obj_get_array(c_arg, &c_len, &c);\n mp_obj_t d args[ARG_d].u_obj;\n\n //Your code here\n\n return mp_const_none;\n}\nMP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(example_lots_of_parameters_obj, 4, 4, example_lots_of_parameters);\n//\n//:param addr:\n//:param memaddr:\n//:param arg:\n//:param addrsize: Keyword only arg\n//:return:\n//\nSTATIC mp_obj_t example_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {\n enum { ARG_addr, ARG_memaddr, ARG_arg, ARG_addrsize };\n STATIC const mp_arg_t example_readfrom_mem_allowed_args[] = {\n { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },\n { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } },\n { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },\n { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 8 } },\n };\n\n mp_arg_val_t args[MP_ARRAY_SIZE(example_readfrom_mem_allowed_args)];\n mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,\n MP_ARRAY_SIZE(example_readfrom_mem_allowed_args), example_readfrom_mem_allowed_args, args);\n\n mp_int_t addr = args[ARG_addr].u_int;\n mp_int_t memaddr = args[ARG_memaddr].u_int;\n mp_obj_t arg = args[ARG_arg].u_obj;\n mp_int_t addrsize = args[ARG_addrsize].u_int;\n\n //Your code here\n\n return mp_obj_new_str(, );\n}\nMP_DEFINE_CONST_FUN_OBJ_KW(example_readfrom_mem_obj, 1, example_readfrom_mem);\n\nSTATIC const mp_rom_map_elem_t example_module_globals_table[] = {\n\t{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) },\n\t{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },\n\t{ MP_ROM_QSTR(MP_QSTR_lots_of_parameters), MP_ROM_PTR(&example_lots_of_parameters_obj) },\n\t{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&example_readfrom_mem_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);\nconst mp_obj_module_t example_user_cmodule = {\n\t.base = {&mp_type_module},\n\t.globals = (mp_obj_dict_t*)&example_module_globals,\n};\n\nMP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED);\n```\n
\n\n#### Adding fully implemented c functions\nGoing one step further you can directly add c code to be substituted into the c generated code where the \n\"//Your code here comment\" is.\n\nFor example, starting with a fresh example.py you could define it as.\n\n```python\ndef add_ints(a: int, b: int) -> int:\n \"\"\"Adds two integers\n :param a:\n :param b:\n :return:a + b\"\"\"\nadd_ints.code = \" ret_val = a + b;\"\n```\nto get a fully defined function in c\n\nOutput
\n\n```c\n// Include required definitions first.\n#include \"py/obj.h\"\n#include \"py/runtime.h\"\n#include \"py/builtin.h\"\n\n//Adds two integers\n//:param a:\n//:param b:\n//:return:a + b\nSTATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {\n mp_int_t a = mp_obj_get_int(a_obj);\n mp_int_t b = mp_obj_get_int(b_obj);\n mp_int_t ret_val;\n\n ret_val = a + b;\n\n return mp_obj_new_int(ret_val);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);\n\nSTATIC const mp_rom_map_elem_t example_module_globals_table[] = {\n\t{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example) },\n\t{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },\n};\n\nSTATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);\nconst mp_obj_module_t example_user_cmodule = {\n\t.base = {&mp_type_module},\n\t.globals = (mp_obj_dict_t*)&example_module_globals,\n};\n\nMP_REGISTER_MODULE(MP_QSTR_example, example_user_cmodule, MODULE_EXAMPLE_ENABLED);\n```\n
\n\n#### Using functions without a module definition\nIf you don't need the fully module boiler plate, you can generate individual functions with\n```python\nimport ustubby\ndef add_ints(a: int, b: int) -> int:\n \"\"\"add two ints\"\"\"\nadd_ints.code = \" ret_val = a + b;\"\nadd_ints.__module__ = \"new_module\"\n\nprint(ustubby.stub_function(add_ints))\n```\n\n```c\n//add two ints\nSTATIC mp_obj_t new_module_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {\n mp_int_t a = mp_obj_get_int(a_obj);\n mp_int_t b = mp_obj_get_int(b_obj);\n mp_int_t ret_val;\n\n ret_val = a + b;\n\n return mp_obj_new_int(ret_val);\n}\nMP_DEFINE_CONST_FUN_OBJ_2(new_module_add_ints_obj, new_module_add_ints);\n```\n\n#### Parsing Litex Files\nuStubby is also trying to support c code generation from Litex files such as\n```csv\n#--------------------------------------------------------------------------------\n# Auto-generated by Migen (5585912) & LiteX (e637aa65) on 2019-08-04 03:04:29\n#--------------------------------------------------------------------------------\ncsr_register,cas_leds_out,0x82000800,1,rw\ncsr_register,cas_buttons_ev_status,0x82000804,1,rw\ncsr_register,cas_buttons_ev_pending,0x82000808,1,rw\ncsr_register,cas_buttons_ev_enable,0x8200080c,1,rw\ncsr_register,ctrl_reset,0x82001000,1,rw\ncsr_register,ctrl_scratch,0x82001004,4,rw\ncsr_register,ctrl_bus_errors,0x82001014,4,ro\n```\nCurrently only csr_register is supported. Please raise issues if you need to expand this feature.\n```python\nimport ustubby\nmod = ustubby.parse_csv(\"csr.csv\")\nprint(ustubby.stub_module(mod))\n```\n\n## Running the tests\nInstall the test requirements with \n```bash\npip install -r requirements-test.txt\n```\nInstall the package in editable mode\n```bash\npip install -e .\n```\nRun the tests\n```bash\npytest\n```\n\n## Check out the docs\n\nTBD\n\n## Contributing\n\nContributions are welcome. Get in touch or create a new pull request.\n\n## Credits\nInspired by \n- [Extending MicroPython: Using C for Good](https://youtu.be/fUb3Urw4H-E)\n- [Online C Stub Generator](https://gitlab.com/oliver.robson/mpy-c-stub-gen)\n- [Micropython](https://micropython.org) \n\nPyCon AU 2019 Sprints\n\n## Authors\n\n* **Ryan Parry-Jones** - *Original Developer* - [pazzarpj](https://github.com/pazzarpj)\n\nSee also the list of [contributors](https://github.com/pazzarpj/micropython-ustubby/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details\n\n\n",
"description_content_type": "text/markdown",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/pazzarpj/micropython-ustubby",
"keywords": "",
"license": "",
"maintainer": "",
"maintainer_email": "",
"name": "ustubby",
"package_url": "https://pypi.org/project/ustubby/",
"platform": "",
"project_url": "https://pypi.org/project/ustubby/",
"project_urls": {
"Homepage": "https://github.com/pazzarpj/micropython-ustubby"
},
"release_url": "https://pypi.org/project/ustubby/0.1.1/",
"requires_dist": null,
"requires_python": ">=3.6",
"summary": "Micropython c stub generator",
"version": "0.1.1"
},
"last_serial": 5648530,
"releases": {
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "a502a161ed6c8db784de5a4da4a7c567",
"sha256": "cb49dec3073d29fd938ec87bc0cacbc734c5f40cc62435d2eb2ce4e5ef22addc"
},
"downloads": -1,
"filename": "ustubby-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a502a161ed6c8db784de5a4da4a7c567",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 5653,
"upload_time": "2019-08-06T13:03:36",
"url": "https://files.pythonhosted.org/packages/79/0f/46a2e0a35cb701353bc2d6cda44dea74e58c4025765cbdeda6a75c582f5b/ustubby-0.1.0-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "3ed11df315237238e84ac2f004ffdc38",
"sha256": "e2f53e251d6772b9c3600c0d5c62613086c519d4aebdfd1a06b10281cd85e6e7"
},
"downloads": -1,
"filename": "ustubby-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "3ed11df315237238e84ac2f004ffdc38",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 7433,
"upload_time": "2019-08-06T13:03:38",
"url": "https://files.pythonhosted.org/packages/e4/4f/4bd49f7ba9b3d4b17e7dc8e9f32f585b727ea550df32b715d9405ff1670b/ustubby-0.1.0.tar.gz"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "9cdf8fd8ccc653013b8c908d84d0fa23",
"sha256": "3f5ff52526084267c504522fb31541a8d4894bb3c39b3364083528abdb33b080"
},
"downloads": -1,
"filename": "ustubby-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9cdf8fd8ccc653013b8c908d84d0fa23",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 9048,
"upload_time": "2019-08-08T07:21:57",
"url": "https://files.pythonhosted.org/packages/cb/8a/07489b1736dce07ea880dddbb76518211aa95e8049f0b42be7b3db2df051/ustubby-0.1.1-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "3f2867a301a31ee5f9d78b826d35f7f7",
"sha256": "fde8002e23cf4a12bdcaec11362cb6579e1725dfad63bf2af1f8532bb2fd3d65"
},
"downloads": -1,
"filename": "ustubby-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "3f2867a301a31ee5f9d78b826d35f7f7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 9752,
"upload_time": "2019-08-08T07:21:59",
"url": "https://files.pythonhosted.org/packages/bc/33/32bbf82ac1f769a9dbd1d37c19d71785d0e42af65ed96695f5254964f10f/ustubby-0.1.1.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "9cdf8fd8ccc653013b8c908d84d0fa23",
"sha256": "3f5ff52526084267c504522fb31541a8d4894bb3c39b3364083528abdb33b080"
},
"downloads": -1,
"filename": "ustubby-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9cdf8fd8ccc653013b8c908d84d0fa23",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 9048,
"upload_time": "2019-08-08T07:21:57",
"url": "https://files.pythonhosted.org/packages/cb/8a/07489b1736dce07ea880dddbb76518211aa95e8049f0b42be7b3db2df051/ustubby-0.1.1-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "3f2867a301a31ee5f9d78b826d35f7f7",
"sha256": "fde8002e23cf4a12bdcaec11362cb6579e1725dfad63bf2af1f8532bb2fd3d65"
},
"downloads": -1,
"filename": "ustubby-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "3f2867a301a31ee5f9d78b826d35f7f7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 9752,
"upload_time": "2019-08-08T07:21:59",
"url": "https://files.pythonhosted.org/packages/bc/33/32bbf82ac1f769a9dbd1d37c19d71785d0e42af65ed96695f5254964f10f/ustubby-0.1.1.tar.gz"
}
]
}