wren-lang / wren

The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.
http://wren.io
MIT License
6.9k stars 552 forks source link

Unable to call instance method from C #823

Open mode777 opened 4 years ago

mode777 commented 4 years ago

Hey everyone. I just can't seem to figure out how to call a instance method from C. Here's a minimal example:

Here is my wren code

class A {
  construct new() {}
  b(){
    System.print("I was called yeeehaa!")
  }
}
var a = A.new()
ForeignFuncs.callB(a)

An here is my C code

static void callback(WrenVM* vm){
  WrenHandle* callHandle = wrenMakeCallHandle(vm, "b()");
  WrenHandle* instHandle = wrenGetSlotHandle(vm, 1);
  wrenSetSlotHandle(vm, 0, instHandle);
  wrenCall(vm, callHandle);
}

However this does not seem to work. Anyone has an idea why this is not working?

Wren-Error in module '(null)' line -1: Fn does not implement 'b()'.
Wren-Error in module 'main' line 22: (script)
Segmentation fault

`

ruby0x1 commented 4 years ago

Are you trying in debug? One important note is that you can't call from a foreign function. WrenCall inside foreign is an assert (which you'd see in debug)

mode777 commented 4 years ago

Hi ruby, thanks for pointing this out. Yep, I did not build in debug mode but this is most likely a re-entrancy issue - which, as pointed out, is not possible.

However, I cant figure out how to mitigate this. In my current setup, wren is running my main loop. So there is no way around re-entrancy. E.g. main_loop (wren) -> poll_events (c) -> input_callback (c) -> wren_method (wren) !! - reentrancy

I guess a work-around for this, is to move the main loop to c, right?

mhermier commented 4 years ago

There is AFAIK no real solution to this problem with current API. The only practical solution is to make C code less smart, pull the event from C to wren an do the callback from there. I'm trying to solve this problem since the introduction of libuv dependency to wren. It introduced some hacky code to circumvent the problem, that is not really safe and reusable.