I have a Racket module hw.rkt:
#lang racket/base
(provide hw)
(define (hw) (displayln "Hello, world!"))
I would like to write a C program that embeds the Racket runtime and applies the procedure (hw)
.
There is example code here which demonstrates how to embed the Racket runtime and apply a procedure that is in racket/base
, or to read and evaluate an S-expression, but I've had no luck modifying this code to allow access to the (hw)
procedure.
This page seems to say that it is possible to do what I want to do by first compiling hw.rkt to hw.c using raco ctool --c-mods
, and this works just fine when I try it, but I still can't actually access the (hw)
procedure.
If someone could post a complete example program, or simply describe which C functions to use, I would be very appreciative. From there I can figure out the rest.
Editing to provide examples of things I have tried.
I modified the example program to get rid of the "evaluate command line arguments" bit and skip straight to the REPL so that I could experiment. Thus (with "hw.c" the result of running raco ctool --c-mods hw.c ++libs racket/base hw.rkt
):
#define MZ_PRECISE_GC
#include "scheme.h"
#include "hw.c"
static int run(Scheme_Env *e, int argc, char *argv[])
{
Scheme_Object *curout = NULL, *v = NULL, *a[2] = {NULL, NULL};
Scheme_Config *config = NULL;
int i;
mz_jmp_buf * volatile save = NULL, fresh;
MZ_GC_DECL_REG(8);
MZ_GC_VAR_IN_REG(0, e);
MZ_GC_VAR_IN_REG(1, curout);
MZ_GC_VAR_IN_REG(2, save);
MZ_GC_VAR_IN_REG(3, config);
MZ_GC_VAR_IN_REG(4, v);
MZ_GC_ARRAY_VAR_IN_REG(5, a, 2);
MZ_GC_REG();
declare_modules(e);
v = scheme_intern_symbol("racket/base");
scheme_namespace_require(v);
config = scheme_current_config();
curout = scheme_get_param(config, MZCONFIG_OUTPUT_PORT);
save = scheme_current_thread->error_buf;
scheme_current_thread->error_buf = &fresh;
if (scheme_setjmp(scheme_error_buf)) {
scheme_current_thread->error_buf = save;
return -1; /* There was an error */
} else {
/* read-eval-print loop, uses initial Scheme_Env: */
a[0] = scheme_intern_symbol("racket/base");
a[1] = scheme_intern_symbol("read-eval-print-loop");
v = scheme_dynamic_require(2, a);
scheme_apply(v, 0, NULL);
scheme_current_thread->error_buf = save;
}
MZ_GC_UNREG();
return 0;
}
int main(int argc, char *argv[])
{
return scheme_main_setup(1, run, argc, argv);
}
Things that don't work (and their error messages):
Calling (hw)
from the REPL
hw: undefined:
cannot reference undefined identifier
context...:
/usr/local/share/racket/collects/racket/private/misc.rkt:87:7
((dynamic-require 'hw 'hw))
standard-module-name-resolver: collection not found
for module path: hw
collection: "hw"
in collection directories:
context...:
show-collection-err
standard-module-name-resolver
/usr/local/share/racket/collects/racket/private/misc.rkt:87:7
((dynamic-require "hw.rkt" 'hw))
standard-module-name-resolver: collection not found
for module path: racket/base/lang/reader
collection: "racket/base/lang"
in collection directories:
context...:
show-collection-err
standard-module-name-resolver
standard-module-name-resolver
/usr/local/share/racket/collects/racket/private/misc.rkt:87:7
Editing the example code
v = scheme_intern_symbol("racket/base");
scheme_namespace_require(v);
v = scheme_intern_symbol("hw");
scheme_namespace_require(v);
Error:
standard-module-name-resolver: collection not found
for module path: hw
collection: "hw"
in collection directories:
context...:
show-collection-err
standard-module-name-resolver
SIGSEGV MAPERR sicode 1 fault on addr 0xd0
Aborted
(The segfault was probably because I didn't check the value of 'v' before trying to scheme_namespace_require
it.)
Editing the example code mk. 2
v = scheme_intern_symbol("racket/base");
scheme_namespace_require(v);
v = scheme_intern_symbol("hw.rkt");
scheme_namespace_require(v);
Error:
hw.rkt: bad module path
in: hw.rkt
context...:
standard-module-name-resolver
SIGSEGV MAPERR sicode 1 fault on addr 0xd0
Aborted
(re: segfault: as above)
Editing the example code mk. 3
v = scheme_intern_symbol("racket/base");
scheme_namespace_require(v);
v = scheme_intern_symbol("./hw.rkt");
scheme_namespace_require(v);
(as above)
Editing the example code mk. 4
/* read-eval-print-loop, uses initial Scheme_Env: */
a[0] = scheme_intern_symbol("hw");
a[1] = scheme_intern_symbol("hw");
v = scheme_dynamic_require(2, a);
(as mk. 1, save the segfault)
Editing the example code mk. 5
/* read-eval-print loop, uses initial Scheme_Env: */
a[0] = scheme_intern_symbol("hw");
a[1] = scheme_eval(a[0], e);
scheme_apply(a[1], 0, NULL);
Error:
hw: undefined;
cannot reference undefined identifier
Answered by Matthew Flatt here. When using dynamic-require
, I needed to quote the name of the module twice, not once. Thanks to Dr. Flatt for their assistance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With