From 447a05f7c3f5bd451dd553003d99a354ed4e2867 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 21 Jun 2014 12:00:50 +0900 Subject: [PATCH] add C API documentation --- docs/capi.rst | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 97 insertions(+) create mode 100644 docs/capi.rst diff --git a/docs/capi.rst b/docs/capi.rst new file mode 100644 index 00000000..b2e3ad0f --- /dev/null +++ b/docs/capi.rst @@ -0,0 +1,96 @@ +C API +===== + +You can write Picrin's extension by yourself from both sides of C and Scheme. This page describes the way to control the interpreter from the C world. + +Extension Library +----------------- + +If you want to create a contribution library with C, the only thing you need to do is make a directory under contrib/. Below is a sample code of extension library. + +* contrib/add/CMakeLists.txt:: + + list(APPEND PICRIN_CONTRIB_INITS "void pic_init_add(pic_state *)\; pic_init_add(pic)\;") + list(APPEND PICRIN_CONTRIB_SOURCES ${PROJECT_SOURCE_DIR}/contrib/add/add.c) + +* contrib/add/add.c:: + + #include "picrin.h" + + static pic_value + pic_add(pic_state *pic) + { + double a, b; + + pic_get_args(pic, "ff", &a, &b); + + return pic_float_value(a + b); + } + + void + pic_init_add(pic_state *pic) + { + pic_deflibrary ("(picrin add)") { + pic_defun(pic, "add", pic_add); + } + } + +After recompiling the interpreter, the library "(picrin add)" is available in the REPL, which library provides a funciton "add". + +User-data vs GC +^^^^^^^^^^^^^^^ + +When you use dynamic memory allocation inside C APIs, you must be caseful about Picrin's GC. Fortunately, we provides a set of wrapper functions for complete abstraction of GC. In the case below, the memory (de)allocators *create_foo* and *finalize_foo* are wrapped in pic_data object, so that when an instance of foo losts all references from others to it picrin can automatically finalize the orphan object:: + + /** foo.c **/ + #include + #include "picrin.h" + #include "picrin/data.h" + + /* + * C-side API + */ + + struct foo { + // blah blah blah + }; + + struct foo * + create_foo () + { + return malloc(sizeof(struct foo)); + } + + void + finalize_foo (void *foo) { + struct foo *f = foo; + free(f); + } + + + /* + * picrin-side FFI interface + */ + + static const pic_data_type foo_type = { "foo", finalize_foo }; + + static pic_value + pic_create_foo(pic_state *pic) + { + struct foo *f; + struct pic_data *dat; + + pic_get_args(pic, ""); // no args here + + f = create_foo(); + + data = pic_data_alloc(pic, &f, md); + + return pic_obj_value(data); + } + + void + pic_init_my_data(pic_state *pic) + { + pic_defun(pic, "create-my-data", pic_create_foo); // (create-foo) + } diff --git a/docs/index.rst b/docs/index.rst index 0b1a4491..5c620a0d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,6 +15,7 @@ Contents: deploy.rst lang.rst libs.rst + capi.rst Indices and tables ==================