summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--foreign.c34
-rw-r--r--test.toc32
-rw-r--r--types.c2
-rw-r--r--types.h1
4 files changed, 36 insertions, 33 deletions
diff --git a/foreign.c b/foreign.c
index 8a1b7b6..c7951a9 100644
--- a/foreign.c
+++ b/foreign.c
@@ -223,29 +223,34 @@ static bool arg_list_add(av_alist *arg_list, Value *val, Type *type, Location wh
}
static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) {
- assert(fn->flags & FN_EXPR_FOREIGN);
- const char *lib = fn->foreign.lib;
- const char *name = fn->foreign.name;
+ void (*fn_ptr)() = fn->foreign.fn_ptr;
+ if (!fn_ptr) {
+ assert(fn->flags & FN_EXPR_FOREIGN);
+ const char *lib = fn->foreign.lib;
+ const char *name = fn->foreign.name;
- /* TODO: IMPORTANT: only open libraries once */
- void *handle = dlopen(lib, RTLD_LAZY);
- if (!handle) {
- err_print(call_where, "Could not open dynamic library: %s.", lib);
- return false;
- }
+ /* TODO: IMPORTANT: only open libraries once */
+ void *handle = dlopen(lib, RTLD_LAZY);
+ printf("Load %s\n",lib);
+ if (!handle) {
+ err_print(call_where, "Could not open dynamic library: %s.", lib);
+ return false;
+ }
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
- void (*fn_ptr)() = dlsym(handle, name);
+ fn_ptr = dlsym(handle, name);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
-
- if (!fn_ptr) {
- err_print(call_where, "Could not get function from dynamic library: %s.", name);
- return false;
+
+ if (!fn_ptr) {
+ err_print(call_where, "Could not get function from dynamic library: %s.", name);
+ return false;
+ }
+ fn->foreign.fn_ptr = fn_ptr;
}
av_alist arg_list;
@@ -260,7 +265,6 @@ static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_w
(void)fn_type; (void)args;
- dlclose(handle);
return true;
}
diff --git a/test.toc b/test.toc
index 32c08e5..3cd0b33 100644
--- a/test.toc
+++ b/test.toc
@@ -5,29 +5,25 @@ import ::= fn(x :: []char) &Package {
p_ptr
};
-puts :: fn(&char) i32 = #foreign "puts", "libc.so.6";
-dprintf :: fn(i32, &char, f64) i32 = #foreign "dprintf", "libc.so.6";
+cputs :: fn(&char) i32 = #foreign "puts", "libc.so.6";
-hw ::= fn() i32 {
- s := "Hello, world!\0";
- puts(&s[0])
+puts ::= fn(s: []char) i32 {
+ cstr := new(char, s.len + 1);
+ each i := 0..s.len-1 {
+ cstr[i] = s[i];
+ }
+ cstr[s.len] = '\0';
+ ret := cputs(&cstr[0]);
+ del(cstr);
+ ret
};
-
-sqrt :: fn(f64) f64 = #foreign "sqrt", "libm.so.6";
-
foo ::= fn() i32 {
- x := sqrt(2.0);
- s := "sqrt(2) = %f\n\0";
- dprintf(2, &s[0], x)
+ puts("Hi");
+ puts("Hello");
+ puts("Hey")
};
main ::= fn() {
- // io ::= import("std/io");
- // io.puts("Hello, world!");
- // hw();
- x ::= hw();
- y ::= foo();
- sqrt2 ::= sqrt(2.0);
- // y ::= abort_1();
+ x ::= foo();
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 5c21557..d0026f3 100644
--- a/types.c
+++ b/types.c
@@ -2236,11 +2236,13 @@ static bool types_decl(Typer *tr, Declaration *d) {
/* make sure no one tries to use these */
d->foreign.name = NULL;
d->foreign.lib = NULL;
+
FnExpr *f = d->val.fn = typer_calloc(tr, 1, sizeof *d->expr.fn);
f->flags = FN_EXPR_FOREIGN;
f->where = d->expr.where = d->where;
f->foreign.name = name_cstr;
f->foreign.lib = lib_cstr;
+ f->foreign.fn_ptr = NULL;
d->flags |= DECL_FOUND_VAL;
}
diff --git a/types.h b/types.h
index 36f21ec..46271aa 100644
--- a/types.h
+++ b/types.h
@@ -620,6 +620,7 @@ typedef struct FnExpr {
struct {
const char *name;
const char *lib;
+ void (*fn_ptr)();
} foreign;
};
HashTable instances; /* for fns with constant parameters. the key is a tuple where