Running a delegate inside a C function

Denis Martinez via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jun 7 12:24:58 PDT 2014


I am trying to make a binding for the Jack Audio Connection Kit, which I figured would be a good exercise to start and hopefully to replace C++ for my long term audio work.
I am making good progress (complete C API covered), and currently I am hitting a brick wall where delegates are concerned, while making some proper idiomatic D wrapper classes.

Below I have copied some relevant fragments of code, with the debug messages.

I want to pass a delegate as callback to a C function which is designed to receive the usual (function, void*) arguments.
The delegate is passed to JackClient's process_callback method. Here I make a C function for the purpose of wrapping, which receives into (void*)arg the delegate pointer obtained by &dg. Later in the method I save the delegate in the instance to protect it form being collected.

The problem is, as the C function is being called back, it crashes.
The trace tells that inside it the delegate address is determined correctly, while dg.ptr and dg.funcptr are not.
Am I doing something wrong here?

This is the trace of the execution:
New jack_client with name: Toto
passed to jack_set_process_thread f=0x460950 arg=0x7fff8b32fa20
 delegate with funcptr=0x451d40 ptr=null
Press a key to stop.
1. enter with arg=0x7fff8b32fa20
2. delegate with funcptr=0xa ptr=0x69e8c0
Error executing command run: Program exited with code -11


--- app.d

  JackClient client = new JackClient;
  client.open("Toto", jack_options_t.JackNoStartServer, null);
  scope(exit) client.close();

  writeln("New jack_client with name: " ~ client.get_name());

  client.process_callback = delegate int(jack_nframes_t nframes) {
    writefln("PROCESSING %d frames", nframes);
    return 0;
  };

--- jack/jack.d

alias JackProcessDelegate = int delegate(jack_nframes_t nframes);

class JackClient {
  JackProcessDelegate process_callback_;

  @property
  void process_callback(JackProcessDelegate dg)
  {
    extern (C) JackProcessCallback f = function int(jack_nframes_t nframes, void *arg)
      {
        // return (*cast(JackProcessDelegate *)arg)(nframes);
        int ret;
        writefln("1. enter with arg=%#x", arg);
        auto dg = cast(JackProcessDelegate *)arg;
        writefln("2. delegate with funcptr=%#x ptr=%#x", dg.funcptr, dg.ptr);
        ret = (*dg)(nframes);
        writeln("3. end");
        return ret;
      };

    writefln("passed to jack_set_process_thread f=%#x arg=%#x", f, &dg);
    writefln(" delegate with funcptr=%#x ptr=%#x", dg.funcptr, dg.ptr);

    int ret = jack_set_process_callback(handle_, f, &dg);
    if (ret != 0) {
      throw new JackError("jack_set_process_callback");
    }
    process_callback_ = dg;
  }
}

 		 	   		  


More information about the Digitalmars-d-learn mailing list