2016-03-29 7 views
8

Mam moduł Rakieta hw.rkt:Funkcja połączenia Rakieta z C

#lang racket/base 

(provide hw) 

(define (hw) (displayln "Hello, world!")) 

Chciałbym napisać program w C, który osadza runtime Racket i stosuje procedurę (hw).

Istnieje przykład kodu here, który demonstruje, jak osadzić środowisko wykonawcze rakiety i zastosować procedurę, która jest w racket/base, lub czytać i oceniać wyrażenie S, ale nie miałem szczęścia, modyfikując ten kod, aby umożliwić dostęp do procedura (hw).

This page zdaje się mówić, że jest możliwie robić to, co chcę robić przez pierwsze kompilacji hw.rkt do hw.c użyciu raco ctool --c-mods i to działa dobrze, gdy próbuję go, ale nadal nie mogę faktycznie uzyskać dostęp do procedury (hw).

Jeśli ktoś mógłby opublikować kompletny przykładowy program lub po prostu opisać, które funkcje C należy użyć, byłbym bardzo wdzięczny. Stamtąd mogę wymyślić resztę.


Edytowanie w celu przedstawienia przykładów rzeczy, które próbowałem.

Zmodyfikowałem przykładowy program, aby pozbyć się bitów "Oceń argumenty wiersza poleceń" i przejdź bezpośrednio do REPL, aby móc eksperymentować. W ten sposób (z "hw.c" Wynikiem działania 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); 
} 

rzeczy, które nie działają (i komunikaty o błędach swoje):

Wywołanie (hw) z 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 

Edycja przykładowy kod

v = scheme_intern_symbol("racket/base"); 
scheme_namespace_require(v); 
v = scheme_intern_symbol("hw"); 
scheme_namespace_require(v); 

Błąd:

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 

(segfault był prawdopodobnie dlatego, że nie sprawdzić wartość "v" być przed próbowaniem do scheme_namespace_require it.)

Edytowanie przykładowego kodu mk.2

v = scheme_intern_symbol("racket/base"); 
scheme_namespace_require(v); 
v = scheme_intern_symbol("hw.rkt"); 
scheme_namespace_require(v); 

błędu:

hw.rkt: bad module path 
    in: hw.rkt 
    context...: 
    standard-module-name-resolver 
SIGSEGV MAPERR sicode 1 fault on addr 0xd0 
Aborted 

(Przedmiot segfault: jak wyżej)

Edycja mk przykład kodu. 3

v = scheme_intern_symbol("racket/base"); 
scheme_namespace_require(v); 
v = scheme_intern_symbol("./hw.rkt"); 
scheme_namespace_require(v); 

(jak wyżej)

Edycja mk przykład kodu. 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); 

(jak MK. 1, należy zapisać segfault)

Edycja mk przykład kodu. 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); 

błędu:

hw: undefined; 
cannot reference undefined identifier 

Odpowiedz

3

Odpowiedź Matthew Flatt here. Podczas korzystania z dynamic-require musiałem podać nazwę modułu dwukrotnie, a nie raz. Podziękowania dla doktora Flatt'a za ich pomoc.