Skip to content

Commit

Permalink
Add an 'extern' attribute to struct!
Browse files Browse the repository at this point in the history
So that it can be used to refer to the external variable in a library.
The format is:

make struct! [
	[extern: [lib "sym"]]
	;struct definition
]

example code:
rebol []

ncurses: make library! %libncursesw.so

stdscr: make struct! compose/deep [
	[
		extern: [(ncurses) "stdscr"]
	]
	ptr [pointer]
]

print ["stdscr:" stdscr/ptr]

close ncurses
  • Loading branch information
zsx committed Oct 12, 2015
1 parent c948201 commit 0418a79
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/boot/errors.r
Expand Up @@ -190,6 +190,7 @@ Access: [
permission-denied: [{permission denied}]
process-not-found: [{process not found:} :arg1]

symbol-not-found: [{symbol not found:} :arg1]
]

Command: [
Expand Down
1 change: 1 addition & 0 deletions src/boot/words.r
Expand Up @@ -190,6 +190,7 @@ pointer
addr
raw-memory
raw-size
extern
rebval

;routine
Expand Down
31 changes: 31 additions & 0 deletions src/core/t-struct.c
Expand Up @@ -436,6 +436,37 @@ static void parse_attr (REBVAL *blk, REBINT *raw_size, REBUPT *raw_addr)
Trap_Arg(attr);
}
break;
case SYM_EXTERN:
++ attr;

if (*raw_addr != 0) /* raw-memory is exclusive with extern */
Trap_Arg(attr);

if (!IS_BLOCK(attr)
|| VAL_LEN(attr) != 2) {
Trap_Arg(attr);
} else {
REBVAL *lib;
REBVAL *sym;
void *addr;

lib = VAL_BLK_SKIP(attr, 0);
sym = VAL_BLK_SKIP(attr, 1);

if (!IS_LIBRARY(lib))
Trap_Arg(attr);
if (IS_CLOSED_LIB(VAL_LIB_HANDLE(lib)))
Trap0(RE_BAD_LIBRARY);
if (!ANY_BINSTR(sym))
Trap_Arg(sym);

addr = OS_FIND_FUNCTION(LIB_FD(VAL_LIB_HANDLE(lib)), VAL_DATA(sym));
if (!addr)
Trap1(RE_SYMBOL_NOT_FOUND, sym);

*raw_addr = (REBUPT)addr;
}
break;
/*
case SYM_ALIGNMENT:
++ attr;
Expand Down

0 comments on commit 0418a79

Please sign in to comment.