guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: using guile like a awk filter in a C program.


From: Pierre Lindenbaum
Subject: Re: using guile like a awk filter in a C program.
Date: Fri, 24 May 2024 09:31:21 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0


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)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]