Closed d3nd3 closed 5 months ago
Do you think you could provide a full example that I can just paste into the IDE and try?
For example if I try to strip off all the extra stuff:
// this fails with: Uncaught Error: Function not found!
var c = E.compiledC(`
// double sqrt(double)
double sqrt(double n){
JsVar *f = jsvNewFromFloat(n);
JsVar *M = jspGetNamedVariable("Math");
JsVar *sqrtt = jspGetNamedField(M,"sqrt",false);
JsVar *res = jspeFunctionCall(sqrtt,0,0,false,1,&f);
double d = jsvGetFloat(res);
jsvUnLock(res);
jsvUnLock(f);
jsvUnLock(sqrtt);
jsvUnLock(M);
return d;
}
`);
/* This one might be what you mean? It looks like the 'double'
argument doesn't make it in correctly */
var c = E.compiledC(`
// double sqrt(JsVar, double)
double sqrt(JsVar *v, double n){
JsVar *f = jsvNewFromFloat(n);
JsVar *res = jspeFunctionCall(v,0,0,false,1,&f);
double d = jsvGetFloat(res);
jsvUnLock(res);
jsvUnLock(f);
return d;
}
`);
print(c.sqrt(x=>{print(x);return Math.sqrt(x)}, 20));
/* This one works - using just integers */
var c = E.compiledC(`
// int sqrt(JsVar, int)
int sqrt(JsVar *v, int n){
JsVar *f = jsvNewFromInteger(n);
JsVar *res = jspeFunctionCall(v,0,0,false,1,&f);
int d = jsvGetInteger(res);
jsvUnLock(res);
jsvUnLock(f);
return d;
}
`);
print(c.sqrt(x=>{print(x);return Math.sqrt(x)}, 16));
// This one works too, using the vars direct
var c = E.compiledC(`
// JsVar sqrt(JsVar, JsVar)
JsVar *sqrt(JsVar *v, JsVar *n){
JsVar *res = jspeFunctionCall(v,0,0,false,1,&n);
return res;
}
`);
`);
print(c.sqrt(x=>{print(x);return Math.sqrt(x)}, 16));
Sorry for the above not ready to be tested code. I have prepared some code that runs this time.
I have a print() function inside the c, so you can see the value it returns. Its required because the double cannot be converted to anything, not even integer, missing functions.
But yes, I see that it works when integer is input, same as you. The issue arise when double is input into Math.sqrt via c.
Run the below code:
var c = E.compiledC(`
//double sqrt(void)
//int sqrtInt(void)
void reverse(char str[], int length) {
int start = 0;
int end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
void intToStr(int num, char str[]) {
int i = 0;
int isNegative = 0;
// Handle zero separately
if (num == 0) {
str[i++] = '0';
} else {
// Handle negative numbers
if (num < 0) {
isNegative = 1;
num = -num;
}
// Process individual digits
while (num != 0) {
int digit = num % 10;
str[i++] = digit + '0';
num = num / 10;
}
// Add negative sign if the number was negative
if (isNegative) {
str[i++] = '-';
}
// Reverse the string to get the correct order
reverse(str, i);
}
// Add null terminator
str[i] = '\0';
}
float doubleToFloat(double value) {
union {
double d;
unsigned long long u64;
} doubleUnion;
union {
float f;
unsigned int u32;
} floatUnion;
doubleUnion.d = value;
int sign = (doubleUnion.u64 >> 63) & 1;
int exponent = (int)((doubleUnion.u64 >> 52) & 0x7FF);
unsigned long long fraction = doubleUnion.u64 & 0xFFFFFFFFFFFFF;
if (exponent == 0x7FF) {
floatUnion.u32 = (sign << 31) | 0x7F800000 | ((fraction >> 29) & 0x007FFFFF);
} else if (exponent == 0) {
int shift = 1023 - 127; // Double bias - Float bias
unsigned int denormalized_exp = 1 - shift;
fraction = fraction >> shift;
floatUnion.u32 = (sign << 31) | (denormalized_exp << 23) | ((fraction >> 29) & 0x007FFFFF);
} else {
exponent -= 1023; // Double bias
if (exponent > 127) {
exponent = 127;
} else if (exponent < -126) {
exponent = -126;
}
floatUnion.u32 = (sign << 31) | ((exponent + 127) << 23) | ((fraction >> 29) & 0x007FFFFF);
}
return floatUnion.f;
}
void print(short num) {
JsVar *p = jspGetNamedVariable("print");
char numS[16];
intToStr(num,numS);
JsVar *s = jsvNewFromString(numS);
jsvUnLock(jspeFunctionCall(p,0,0,false,1,&s));
jsvUnLock(s);
jsvUnLock(p);
}
void printS(const char * input) {
JsVar *p = jspGetNamedVariable("print");
JsVar *s = jsvNewFromString(input);
jsvUnLock(jspeFunctionCall(p,0,0,false,1,&s));
jsvUnLock(s);
jsvUnLock(p);
}
double sqrt(void) {
printS("===SqrtDouble===");
JsVar * G = jspGetNamedVariable("global");
JsVar * M = jspGetNamedField(G,"Math",false);
//JsVar * M = jspGetNamedVariable("Math");
JsVar * sqrtt = jspGetNamedField(M,"sqrt",false);
printS("c: input float: ");print(16);JsVar *f = jsvNewFromFloat(16.0);
JsVar * res = jspeFunctionCall(sqrtt,0,0,false,1,&f);
double d_out = jsvGetFloat(res);
printS("c: output int: ");print(jsvGetInteger(res));
printS("c: output double: ");print(doubleToFloat(d_out));
jsvUnLock(res);
jsvUnLock(sqrtt);
jsvUnLock(M);
jsvUnLock(G);
return d_out;
}
int sqrtInt(void) {
printS("===SqrtInt===");
JsVar * G = jspGetNamedVariable("global");
JsVar * M = jspGetNamedField(G,"Math",false);
//JsVar * M = jspGetNamedVariable("Math");
JsVar * sqrtt = jspGetNamedField(M,"sqrt",false);
printS("c: input int: ");print(16);JsVar *f = jsvNewFromInteger(16);
JsVar * res = jspeFunctionCall(sqrtt,0,0,false,1,&f);
double d = jsvGetFloat(res);
int i_out = jsvGetInteger(res);
printS("c: output int: ");print(i_out);
printS("c: output double: ");print(doubleToFloat(d));
jsvUnLock(res);
jsvUnLock(sqrtt);
jsvUnLock(M);
jsvUnLock(G);
return i_out;
}
`);
print(`javascript: output ${c.sqrt()}`);
print(`javascript: output ${c.sqrtInt()}`);
what device are you compiling for?
I just checked and it seems like a while back we switched nRF52-based builds to use a different ABI (softfp) but didn't update the compiler. That'd affect both calling and being called with double args. I've just tweaked it.
I get an error about __aeabi_f2iz
when running your code now, but the double sqrt(JsVar, double)
function I did above does seem to work now.
what device are you compiling for?
I tested with Bangle.js 2.
Closing this as I'm pretty sure the original issue is fixed after recent compiler changes
When I attempt to call the javascript function Math.sqrt() from within here, it returns the same argument I gave it. eg. In 64, out 64.