Closed ScriptBasic closed 7 years ago
please consider wrapping the v7_val_t in a memory block passed by reference:
v7_val_t *vp = (v7_val_t *) malloc(sizeof(v7_val_t));
*vp = result;
besRETURN_LONG(vp);
then, when you need to access that val_t again in another C function invoked by Basic you just need to make sure you interpret the argument as v7_val_t *p
and you dereference it when you pass it to V7 API.
That's a cool idea! I'll give it a shot and let you know if it works. When you say dereference vp, do mean free it?
no, I mean *vp
.
Obviously you have to free it as well, but that's a different problem. Which might not be easy.
A better trick is to pack a 64-bit value in a double:
union dv {
double d;
v7_val_t v;
} ;
double val_to_double(v7_val_t v) {
union dv dv;
dv.v = v;
return dv.d;
}
v7_val_t double_to_val(double d) {
union dv dv;
dv.d = d;
return dv.v;
}
.....
besRETURN_DOUBLE(val_to_double(result));
....
which btw is exactly what we do internally in V7. The V7 values are actually encoded as double floating point numbers, by exploiting the encoding of NaN (not a number) values: see https://docs.cesanta.com/v7/master/#/v7-internals/nan-packing.md/
Derefencing and freeing is handled by the SB extension API.
I like the conversion method you used. Much cleaner.
I think this might work.
I strongly suggest you use the val_to_double/double_to_val
approach;
handling pointers and memory allocations in C is notoriously hard to debug.
I tried to get things working with the conversion routines but I'm having some issues with type casting. I attached the Script BASIC interfacer.c and output from the makefile compile. Can you take a peek and see what I'm doing wrong? sbv7.zip
I didn't review the whole thing, I stopped here:
DIM AS double boolptr;
DIM AS int istrue;
besARGUMENTS("ii")
AT v7, AT istrue
besARGEND
boolptr = v7_mk_boolean(v7, istrue);
besRETURN_DOUBLE(JS2Double(boolptr));
you're incorrectly assigning a v7_val_t
into a variable of type double
(with a confusing name of boolptr btw).
v7_mk_boolean
returns a v7_val_t
and if you want to convert it properly to a boolean you need to do it via the JS2Double
function you have at the beginning of your file.
Automatic C conversion as in double foo = v7_mk_boolean(....)
doesn't work, because it will try to represent a 64-bit integer as floating point number (i.e. converting integer to a floating point representation of the same numerical value). While the trick done by JS2Double
is to store the exact same bit pattern in a double
variable which is 64-bit on every platform and thus can be passed around by your BASIC interpreter and later be converted back to a 64-bit integer.
Thus it should be:
DIM AS v7_val_t boolval;
DIM AS int istrue;
besARGUMENTS("ii")
AT v7, AT istrue
besARGEND
boolval = v7_mk_boolean(v7, istrue);
besRETURN_DOUBLE(JS2Double(boolval));
Another very basic issue I found is:
besFUNCTION(js_get_bool)
DIM AS unsigned long v7;
DIM AS double boolptr;
DIM AS int truefalse;
besARGUMENTS("ii")
AT v7, AT truefalse
besARGEND
truefalse = v7_get_bool(v7, Double2JS(boolptr));
besRETURN_LONG(truefalse);
besEND
Here you're just confusing input and output variables.
Which should obviously be:
besFUNCTION(js_get_bool)
DIM AS unsigned long v7;
DIM AS double boolval;
DIM AS long truefalse;
besARGUMENTS("ir")
AT v7, AT boolval
besARGEND
truefalse = v7_get_bool(v7, Double2JS(boolval));
besRETURN_LONG(truefalse);
besEND
I didn't look at any further issues, especially since you didn't describe where to look in particular.
I suggest you focus more and use more care when programming; that's the path to success. Otherwise, you'll not only have serious trouble making this work, but you will also make people less likely to help you again.
I suggest you read a good book about C, for example "The C Programming Language (Second Edition)" by Brian Kernighan and Dennis Ritchie.
I changed all the double's to v7_val_t types but still getting errors.
You are using non-standard variable types and your documentation sucks. I'm trying to get through this and don't need the "read a beginner's C book". The references to ptr were early on in the program definition before unrevealing the mysteries behind the code.
C:\sbgcc\source\extensions\js>mingw32-make -B
gcc -w -D_WIN32 -m32 -ggdb -c -o ..\..\bin\mod\obj\js\s_interface.o interface.c
interface.c: In function 'js_own':
interface.c:219:24: error: incompatible type for argument 1 of 'Double2JS'
v7_own(v7, Double2JS(&cvar));
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t ** {aka long long unsigned int **}'
static v7_val_t Double2JS(double d) {
^
interface.c: In function 'js_disown':
interface.c:230:35: error: incompatible type for argument 1 of 'Double2JS'
found = v7_disown(v7, Double2JS(&cvar));
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t ** {aka long long unsigned int **}'
static v7_val_t Double2JS(double d) {
^
interface.c: In function 'js_get_string':
interface.c:453:39: error: incompatible type for argument 1 of 'Double2JS'
sbstr = v7_get_string(v7, Double2JS(&resultptr), NULL);
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t * {aka long long unsigned int *}'
static v7_val_t Double2JS(double d) {
^
interface.c: In function 'js_get_cstring':
interface.c:465:40: error: incompatible type for argument 1 of 'Double2JS'
sbcstr = v7_get_string(v7, Double2JS(&cstrptr), &cstrlen);
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t * {aka long long unsigned int *}'
static v7_val_t Double2JS(double d) {
^
interface.c: In function 'js_apply':
interface.c:705:92: error: incompatible type for argument 1 of 'Double2JS'
rtncode = v7_apply(v7, Double2JS(funcptr), V7_UNDEFINED, Double2JS(argsptr), Double2JS(&result));
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t * {aka long long unsigned int *}'
static v7_val_t Double2JS(double d) {
^
interface.c:707:97: error: incompatible type for argument 1 of 'Double2JS'
rtncode = v7_apply(v7, Double2JS(funcptr), Double2JS(objptr), Double2JS(argsptr), Double2JS(&result));
^
interface.c:56:17: note: expected 'double' but argument is of type 'v7_val_t * {aka long long unsigned int *}'
static v7_val_t Double2JS(double d) {
^
Makefile:17: recipe for target 'bin\mod\obj\js\s_interface.o' failed
mingw32-make: *** [bin\mod\obj\js\s_interface.o] Error 1
C:\sbgcc\source\extensions\js>
I think the problems I'm having with Script BASIC and V7 is that SB only supports LONG, DOUBLE, ARRAYS (index & associative) and STRINGS (C str & binary) As you say, I got lucky with a SB 64 bit long and v7_val_t on Umuty 64 bit. It's a shame we couldn't connect on Windows. I might give Script BASIC 64 bit Windows another try.