How to pass a function to an extern, (such as wasm host) [solved]

I’ve figured this out, but I want to make sure what I have learnt is findable for the next person.
I couldn’t find any direct examples in the documentation, so ended up going off code that I found in github issues…

extern fn onReady(cb: fn ()callconv(.C)  void) void;

fn cb () callconv(.C)  void { 
  onReady(cb2);
}
fn cb2 () callconv(.C)  void { }

export fn init () void {
  onReady(cb);
}

init passes cb to onReady(cb) and then when cb is called it passes cb2 to onReady(cb2)

note that onReady is defined with a function type, but not a function pointer, as you would do so in C.
using a function pointer does actually work but then on the javascript side onReady will get a memory address of value the function table entry, but this way it just gets the value.

for completeness, this is the javascript to load the wasm

const fs = require('fs');
const source = fs.readFileSync("./cb_c.wasm");
const typedArray = new Uint8Array(source);
var memory

;(async function () {
  var callback
  var buffer = Buffer.alloc(0)
  var result = await WebAssembly.instantiate(typedArray, {
    env: {
    onReady: function (fn_ptr) {
      var table = result.instance.exports.__indirect_function_table
      var memory = Buffer.from(result.instance.exports.memory.buffer)
      console.log('fn_ptr', fn_ptr)
      
        callback = result.instance.exports.__indirect_function_table.get(fn_ptr)
        //if you defined as a function pointer, this would be necessary:
        //callback = result.instance.exports.__indirect_function_table.get(memory.readUInt32LE(fn_ptr))
    },
  }})
  result.instance.exports.init()
  callback()
}())

and here is the equivalent c

typedef void (*callback)();
void onReady (callback* cb);

void cb2 () { }
void cb () { 
  onReady(&cb2);
}

void init () {
  onReady(&cb);
}