I want to call scheme from C.
The C loop scans the binary data and a scheme script would be used to
accept/reject a record. Something like
./my-c-program --filter '(and (is-male?) (is-german?) )' persons.data >
male_from_germany.data
- furthermore, what's the best practice to include the user's script in
a larger script that would include the definitions of `variant-is-snp?`
, `variant-allele-count`, etc...
Maybe modules?
Ok , this it what I got so far. I tested my idea with a C program scanning a
stream of integers on stdin . I put the C code and the Makefile below (or you
can read it at https://gist.github.com/lindenb/7b7793ced81fc3a4a566333f5149d65a
) :
The invocation looks like:
seq 1 100 | ./a.out '(= (modulo (_get) 7) 0)'
7
14
21
28
35
42
49
56
63
70
77
84
91
98
where (_get) returns the current integer.
Is it the correct way to initialize the script ?
it looks ugly. Currently the user just define the 'filter' part and then I
include this string in a larger code. Ant how should I design this if I want to
include modules, custom functions,... ?
Furthermore, I'd like to include a module that would be embedded in the C code
, in a big const string to avoid any external file, it it possible ?
Thank you for your suggestions
Pierre
/***************** C code ************************************************/
#include <stdio.h>
#include <libguile.h>
struct Global {
/** inputstream */
FILE* in;
/** currrent value */
int value;
/** contains script as string */
char buffer[2048];
};
static struct Global global;
/** retrieve the next record, return #t on success */
static SCM _next () {
int ret = fscanf(global.in,"%d", &(global.value));
if(ret!=1) return SCM_BOOL_F;
return SCM_BOOL_T;
}
/** get current number */
static SCM _get () {
return scm_from_int(global.value);
}
/** output current number */
static SCM _emit () {
fprintf(stderr,"%d\n",global.value);
return SCM_BOOL_T;
}
/** dispose memory associated */
static SCM _dispose () {
return SCM_BOOL_T;
}
static void*
inner_main (void *data)
{
struct Global* g= (struct Global*)data;
scm_c_define_gsubr("_next", 0, 0, 0, _next);
scm_c_define_gsubr("_get", 0, 0, 0, _get);
scm_c_define_gsubr("_emit", 0, 0, 0, _emit);
scm_c_define_gsubr("_dispose", 0, 0, 0, _dispose);
scm_c_eval_string(g->buffer);
return 0;
}
int main(int argc,char** argv) {
if(argc!=2) return -1;
global.value=1;
global.in = stdin;
sprintf(global.buffer,"(while (_next) (if %s (_emit) ) (_dispose) )
",argv[1]);
scm_with_guile(inner_main,(void*)&global);
return 0;
}
/***************** Makefile
************************************************/GUILE_VERSION=2.2
# Tell the C compiler where to find <libguile.h>
CFLAGS=`pkg-config --cflags guile-$(GUILE_VERSION)`
# Tell the linker what libraries to use and where to find them.
LIBS=`pkg-config --libs guile-$(GUILE_VERSION)`
test: a.out
seq 1 100 | ./a.out '(= (modulo (_get) 7) 0)'
a.out: filter.c
$(CC) $(CFLAGS) -o $@ $< $(LIBS)