Load and compile python file without system file with MicroPython

420 views Asked by At

MicroPython Github that I am using.

I want to run some very simple code on MicroPython and I have successfully called C functions from Python and vice versa with my own code. However, it only works on Windows (Visual Studio IDE).

Now, I want to load this code onto a Cortext M4 chip using the Crossworks IDE. It took some work to figure out the dependencies and generated header files when I tried to copy and paste the code from Visual Studio to crossworks.

It works only with basic functions like printf but ignores my function calls. The reason is that it tries to look for my Python file but could not find it.

Here is the code that I have to load and compile Python code:

void compile_pyfile(const char* fileName) {
    //load and compile python src file
    mp_lexer_t *lex = mp_lexer_new_from_file(fileName);
    mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
    mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false);
    mp_call_function_0(module_fun);
}

And here is the function that calls the output of that Python compile:

mp_obj_t call_py_func3(mp_obj_t* arr) {
    const char* fileName = "Hello.py";
    const char* funcName = "ret = test_array_C(*args)";
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        qstr inArrName = qstr_from_str("args");
        mp_store_global(inArrName, *arr);
        compile_pyfile(fileName);
        exec_cmd(funcName);
        nlr_pop();
        return 0;
    } else {
        // uncaught exception
        return (mp_obj_t)nlr.ret_val;
    }
}

I don't know for sure what needs to be done here to make it work without system files. Here is similar code provided in micropython-master from Github. This is in a string rather than a file.

void do_str(const char *src, mp_parse_input_kind_t input_kind) {
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
        qstr source_name = lex->source_name;
        mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
        mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true);
        mp_call_function_0(module_fun);
        nlr_pop();
    } else {
        // uncaught exception
        mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
    }
}
1

There are 1 answers

0
Dave Hylands On

In order for MicroPython to call the C functions, they need to be registered with the interpreter. I have an oldish example over here: https://github.com/dhylands/micropython/commit/b801dbd39eb323494f946c13362f4957f5d7281b This creates a module called c_sample.

If you look at the changes to the mpconfigport.h file you'll where it adds &mp_module_c_sample to MICROPY_PORT_BUILTIN_MODULES This is what allows import c_sample to work.

Without a filesystem, you can also have python source files and pre-compiled bytecode (.mpy) files included as frozen files, and these can be used. The teensey port has no filesystem and uses this technique.