Skip to content

Call C functions from AtomVM (Erlang/Elixir on microcontrollers)

Notifications You must be signed in to change notification settings

tlack/cproto2atomnif

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cproto2atomnif

Plug existing C code into your AtomVM applications quickly and easily.

cproto2atomnif is a Python script that reads C prototype header files and spits out code to use them from inside Erlang or Elixir on AtomVM.

The process of creating these AtomVM nifs is very straightforward, but there is a lot of boilerplate involved. This script automates that by creating the C source code for the AtomVM nif component.

You still need to edit the resulting code to add your specific validation logic, etc.

example

$ cat test-library.c
int add(int a, int b) {
	        return a+b;
}
$ cat test-library.h
int add(int a, int b);
$ cproto2atomnif test-library.h testlib > testlib.c
$ cat testlib.c

    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include <esp_log.h>
    #include <stdlib.h>
    #include <defaultatoms.h>
    #include <interop.h>
    #include <nifs.h>
    #include <port.h>
    #include <term.h>

    static term nif_testlib_add(Context *ctx, int argc, term argv[]) {
        printf("entering testlib:add/%d", argc); 
        if (argc != 2) {
            printf("testlib:add/%d - expected %d args, got %d", 2, 2, argc);
            return BADARG_ATOM;
        }
        
        int a = (int)term_to_int(argv[0]);
        int b = (int)term_to_int(argv[1]);
        int func_result = add(a, b);
       
	term atom_val = term_from_int32(func_result);
        VALIDATE_VALUE(atom_val, term_is_integer);
        return atom_val;
    }
    static const struct Nif testlib_add_nif_info = 
    {
        .base.type = NIFFunctionType,
        .nif_ptr = nif_testlib_add
    };

    const struct Nif *testlib_get_nif(const char *nifname)
    {
        if (strcmp("testlib:add/2", nifname) == 0) {
            return &testlib_add_nif_info;
        }

        return NULL;
    }

Now compile and burn your firmware and scripts to the device, and the following should work:

X = testlib:add(5, 7)

status

  • Does NOT support precompiler macros, or real .h files. You must simplify your prototypes before use!
  • Rough, barbarian-style first draft
  • Supports only int (of various kinds), float/double, and char*/uint8_t* (as beam binaries).
  • Very crude regular expression-based parser; should switch to pyclanguage
  • Would be cool to have more config options, or any config options.
  • Needs docs; see test.py for some ideas about what it supports

note on c++

To call C++ from a ESP-IDF toolkit component, which is C, the C++ code will need to declare the target function with extern "C" at the site of the definition (not the prototype).

Furthermore, neither C nor this tool understand class method invocation, so your prototypes used with cproto2atomnif should only refer to thing_do_blah, not Thing.do_blah.

motivation

There is a lot of existing Arduino code that I need to call from Erlang code running in AtomVM!

About

Call C functions from AtomVM (Erlang/Elixir on microcontrollers)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages