I'm trying to bring Shixin's C2R3 up to date, which is basically frozen in 2015.
He made it as a library, where you define some hooks...include C2R3...and then call "compile" which would use those hooks:
Rebol [
Title: "My C2R3 Binding Generator for the %foo.c Project"
]
cfunction-filter: func [return: [logic!] f [object!]] [
;
; this handler gets called whenever Clang sees a funciton
;
if find e.name "foo_api_" [return true] ; we want it in the binding
return false ; ignore this function in the C file
]
OUTPUT: %foo-ffi.r
do %c2r3.r
compile %foo.c
So C2R3 is implicitly picking up parameters, like OUTPUT and CFUNCTION-FILTER, which it uses in the COMPILE.
That's Not How It Works Anymore
Modules and Scripts are isolated from each other. So C2R3 can't see these definitions.
You can do some hacks to simulate the old behavior... basically by LOAD-ing code, binding it into your script's context, and then EVAL'ing it.
The boring way that basically everyone else handles this would be to have some kind of configuration object that you pass to COMPILE.
Rebol [
Title: "My Better C2R3 Binding Generator for %foo.c"
]
c2r3: import %c2r3.r
config: make c2r3.config! [
INPUT: %foo.c
OUTPUT: %foo-ffi.r
cfunction-filter: func [return: [logic?] f [object!]] [
if find e.name "foo_api_" [return okay]
return null
]
]
c2r3/compile config
But... that is boring.
With DO:ARGS you could conceivably fold the config and the import together:
Rebol [
Title: "One-Shot C2R3 Binding Generator for %foo.c"
]
source: join %foo %.c ; you could still run code before you DO
do:args %c2r3.r [
INPUT: source
OUTPUT: %foo-ffi.r
cfunction-filter: func [return: [logic?] f [object!]] [
if find e.name "foo_api_" [return okay]
return null
]
]
DO:ARGS doesn't look quite like what I wanted for this, and it's part of why I'd taken back BLOCK! from DO (it no longer is a synonym for EVAL) and it could mean pretty much anything.
source: join %foo %.c ; you could still run code before you DO
do [
%c2r3.r
INPUT: source
OUTPUT: %foo-ffi.r
cfunction-filter: func [return: [logic?] f [object!]] [
if find e.name "foo_api_" [return okay]
return null
]
]
Well, that's not quite the W that I had in mind, but, just pointing out that some options have opened up now that block is available.
Another direction is to kind of say that your scripts themselves are instantiations of the C2R3 "template", e.g. written in the C2R3 dialect, and declare something like that in the header:
Rebol [
Title: "Dialected C2R3 Binding Generator for %foo.c"
Dialect: %c2r3.r
]
(source: join %foo %.c) ; maybe GROUP! evaluates in its own context?
INPUT: (source)
OUTPUT: %foo-ffi.r
cfunction-filter: func [return: [logic?] f [object!]] [
if find e.name "foo_api_" [return okay]
return null
]
So this would be some kind of system where you are more regimented in terms of your file starting from the form of specification that C2R3 expects, and you would have little pockets of code (and if you needed to do more work you'd break that out into another script). This would let you "see" kind of the real goal of the process... the settings that C2R3 wants.
Anyway that's some very half-baked thinking about alternatives to the boring way.
(But I'm just doing it the boring way for now.)