picrin/docs/capi.rst

103 lines
2.1 KiB
ReStructuredText
Raw Normal View History

2014-06-20 23:00:50 -04:00
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.
2015-06-12 16:33:49 -04:00
* contrib/add/nitro.mk
2014-06-20 23:03:40 -04:00
.. sourcecode:: cmake
2014-06-20 23:00:50 -04:00
2015-06-12 16:33:49 -04:00
CONTRIB_INITS += add
CONTRIB_SRCS += contrib/add/add.c
2014-06-20 23:00:50 -04:00
2014-06-20 23:03:40 -04:00
* contrib/add/add.c
.. sourcecode:: c
2014-06-20 23:00:50 -04:00
#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(pic, a + b);
2014-06-20 23:00:50 -04:00
}
void
pic_init_add(pic_state *pic)
{
2014-11-10 11:43:10 -05:00
pic_deflibrary (pic, "(picrin add)") {
2014-06-20 23:00:50 -04:00
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
^^^^^^^^^^^^^^^
2014-06-20 23:03:40 -04:00
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.
.. sourcecode:: c
2014-06-20 23:00:50 -04:00
/** foo.c **/
#include <stdlib.h>
#include "picrin.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_value(pic, md, &foo_type);
2014-06-20 23:00:50 -04:00
return pic_obj_value(data);
}
void
2014-06-20 23:06:28 -04:00
pic_init_foo(pic_state *pic)
2014-06-20 23:00:50 -04:00
{
2014-06-20 23:06:28 -04:00
pic_defun(pic, "create-foo", pic_create_foo); // (create-foo)
2014-06-20 23:00:50 -04:00
}
2014-06-20 23:03:40 -04:00