cesanta / v7

Embedded JavaScript engine for C/C++
Other
1.43k stars 177 forks source link

Can't call js function from C #577

Closed Memorix101 closed 7 years ago

Memorix101 commented 7 years ago

Hey,

I'm trying to call a function from my JavaScript file in my C code.

I used the code from the example to get started https://github.com/cesanta/v7/blob/master/examples/call_js_from_c/call_js_from_c.c

However, I don't get it working and it always shows that error print.

My code:

static void OnUpdate(struct v7 *v7) {
    v7_val_t func, result, args;

    /* Lookup JavaScript function `sum()` */
    func = v7_get(v7, v7_get_global(v7), "Update", 6);

    /* Create arguments array with two numbers */
    args = v7_mk_null();

    /* Call JavaScript function. Pass `undefined` as `this` */
    if (v7_apply(v7, func, V7_UNDEFINED, args, &result) == V7_OK) {
        printf("Result: %g\n", v7_get_double(v7, result));
    }
    else {
        v7_print_error(stderr, v7, "Error while calling sum", result);
    }
}

...

while(1)
{
 OnUpdate(state);
}

My js file:

function Update() {
 print("mooo!");
}

Hope somebody can help me here :)

cpq commented 7 years ago

Please show full sources

Memorix101 commented 7 years ago

// main.cpp

enum v7_err rcode = V7_OK;
struct v7 *state = NULL;
v7_val_t result;

static void OnUpdate(struct v7 *v7) {
    v7_val_t func, result, args;

    /* Lookup JavaScript function `sum()` */
    func = v7_get(v7, v7_get_global(v7), "Update", 6);

    /* Create arguments array with two numbers */
    args = v7_mk_null();

    /* Call JavaScript function. Pass `undefined` as `this` */
    if (v7_apply(v7, func, V7_UNDEFINED, args, &result) == V7_OK) {
        printf("Result: %g\n", v7_get_double(v7, result));
    }
    else {
        v7_print_error(stderr, v7, "Error while calling sum", result);
    }
}

int main()
{
    printf("JavaScript Test");

    //V7 start
    state = v7_create();

    rcode = v7_exec_file(state, "test.js", &result);
        if (rcode != V7_OK) {
            fprintf(stderr, "exec error: %d\n", (int)rcode);
        }

    while(1)
    {
        OnUpdate(state);
    }

  return 0;
}
cpq commented 7 years ago

execute while loop only if v7_exec_file succeeded. Also, I don't see what's in the test.js Closing this - as the problem is your code.

Memorix101 commented 7 years ago

That's all I've got in Test.js

function Update() {
 print("mooo!");
}

@cpq I think the purpose for a post is to help people, instead of closing without having a dialogue

ScriptBasic commented 7 years ago

I have the same problem under Windows returning a valid JavaScript function v7_var_t with v7_get(). Works fine on Linux and on both asking for non-function vars.

ScriptBasic commented 7 years ago

I was hoping to include V7 as an extension module with the Script BASIC Windows 32 bit version I'm about to release. It could give Cesanta a bit more exposure. If I can find resolve with v7_get() and JavaScript function name references, I may still be able to slip it in the release.

ScriptBasic commented 7 years ago

Here is my Linux version that works as expected.

IMPORT js.inc

jscode = """
var sum = function(a, b, c) {
  print (c);
  return a + b; };
"""

JS::CREATE()
JS::EXEC(jscode)
func = JS::GETS(JS::SYS, "sum")
args = JS::MK_ARRAY()
JS::ARRAY_PUSH(args, JS::MK_NUMBER(123.0))
JS::ARRAY_PUSH(args, JS::MK_NUMBER(0.456))
JS::ARRAY_PUSH(args, JS::MK_STRING("Script BASIC"))
result = JS::APPLY(func, 0, args, rcode)
PRINT FORMAT("Result: %g\n", JS::GET_DOUBLE(result))
JS::DESTROY

jrs@jrs-laptop:~/sb/examples/js$ scriba js_callfunc.sb
Script BASIC 
Result: 123.456
jrs@jrs-laptop:~/sb/examples/js$ 

Here is the Windows version of the same code.

IMPORT js.sbi

jscode = """
var sum = function(a, b, c) {
  print (c);
  return a + b; };
"""

JS::CREATE()
JS::EXEC(jscode)
func = JS::GETS(JS::SYS, "sum")
args = JS::MK_ARRAY()
JS::ARRAY_PUSH(args, JS::MK_NUMBER(123.0))
JS::ARRAY_PUSH(args, JS::MK_NUMBER(0.456))
JS::ARRAY_PUSH(args, JS::MK_STRING("Script BASIC"))
result = JS::APPLY(func, 0, args, rcode)
PRINT FORMAT("Result: %g\n", JS::GET_DOUBLE(result))
PRINT "Error: ",JS::GET_ERROR(),"\n"
JS::DESTROY

C:\sbsetup\examples>scriba js_callfunc.sb
Result: -1.#QNAN
Error: value is not a function

C:\sbsetup\examples>
ScriptBasic commented 7 years ago

Here is an example of getting standard (non-function) var references with v7_get() under Windows 32 bit. This same function fails to return a function var reference under Windows only. Works fine under 64 bit Linux. (as stated above)

IMPORT js.inc

jscode = """
var a_int = 64
var a_dbl = 1.23
var a_str = "Script BASIC"
"""

JS::CREATE
JS::EXEC(jscode)
PRINT JS::GET_INT(JS::GETS(JS::SYS, "a_int")),"\n"
PRINT FORMAT("%.2f",JS::GET_DOUBLE(JS::GETS(JS::SYS, "a_dbl"))),"\n"
PRINT JS::GET_STRING(JS::GETS(JS::SYS, "a_str")),"\n"
JS::DESTROY

C:\sbgcc\examples\js>scriba js_getsvar.sb
64
1.23
Script BASIC

C:\sbgcc\examples\js>
ScriptBasic commented 7 years ago

Here is my debug attempt to find what was going wrong under Windows. I have gone as far as I can trouble shooting this and the problem points to the V7 code.

IMPORT js.inc

jscode = """
var sum = function(a, b) {
  return a + b; };
"""
PRINT jscode,"\n"

JS::CREATE()
ok = JS::EXEC(jscode, rcode)
func = JS::GETS(JS::SYS, "sum")
PRINT "func an object? ",JS::IS_OBJECT(func),"\n"
args = JS::MK_ARRAY()
JS::ARRAY_PUSH(args, JS::MK_NUMBER(123.0))
PRINT "args[0] = ",FORMAT("%g",JS::GET_DOUBLE(JS::ARRAY_GET(args, 0))),"\n"
JS::ARRAY_PUSH(args, JS::MK_NUMBER(0.456))
PRINT "args[1] = ",FORMAT("%g",JS::GET_DOUBLE(JS::ARRAY_GET(args, 1))),"\n"
result = JS::APPLY(func, 0, args, rcode)
PRINT "Error: ",JS::GET_ERROR(),"\n"
PRINT "rcode: ",rcode,"\n"
PRINT FORMAT("Result: %g\n", JS::GET_DOUBLE(result))
JS::DESTROY

C:\sbgcc\examples\js>scriba js_callfunc.sb

var sum = function(a, b) {
  return a + b; };

func an object? 0
args[0] = 123
args[1] = 0.456
Error: value is not a function
rcode: 2
Result: -1.#QNAN

C:\sbgcc\examples\js>
ScriptBasic commented 7 years ago

I'm assuming at this point this isn't going to get resolved and I'm wasting my time trying. Sad that something like this kills a project. :-(

Memorix101 commented 7 years ago

Yep, it's pretty sad. I replaced my V7 code with dukglue https://github.com/Aloshi/dukglue

Memorix101 commented 7 years ago

I'm still pretty bitchy about that guy who closed the thread. I included everything necessary to the thread and because he don't wanted to spent time reviewing it properly he closes it. Next time he should just keep quite.

I mean who knows who many people also have this issue and don't look up the closed threads :(

I didn't test my code under Linux, so I can't tell anything about that. All I can say is that I run Windows 10 64bit and can't get the function call

ScriptBasic commented 7 years ago

Script BASIC is ANSI C based and I did look at Duktape as an alternative. I'm pissed all the time I wasted with V7 and the poor attitudes by developers and scanty support. I can't sell my client on using V7 if I can't even sell myself on it.