Thread overview
C callback receives bad pointer argument
Jun 30, 2011
Marco Cosentino
Jun 30, 2011
bearophile
Jun 30, 2011
Andrej Mitrovic
Jun 30, 2011
Andrej Mitrovic
Jul 01, 2011
Marco Cosentino
Jul 01, 2011
Jacob Carlborg
Jul 01, 2011
Andrej Mitrovic
June 30, 2011
Hi,
I'm approaching to D2 with writing a wrapper for the popular JACK2 client library.

I managed the following troubles:
Translated correctly the C callback style into D delegates types with alias.
Managed some segment faluts happened when not using toStringz() with some "strings"
Managed the multithreaded model of jack using __gsharde for global variables needed in a callback

Now I'm in trouble again but this time I can't find a solution without some help.

Have a look at this code:

// jack.di
alias int function(jack_nframes_t nframes, void *arg) JackProcessCallback;
int jack_set_process_callback (jack_client_t *client, JackProcessCallback process_callback, void *arg);

//simple_client.d
int
process (jack_nframes_t nframes, void *arg)
{
    stderr.writeln("process() - data:", arg);
    [...]
}

int main()
{
[...]

    paTestData * data_ptr = &data;
    stderr.writeln("main() - data:",data_ptr);
    jack_set_process_callback (client, &process, data_ptr);

[...]
}

Execution gives:
main() - data:6B6AE0
process() - data:80

of course when trying to access the real data casting to its original type I get a segmentation fault.

I think that part of the problem is that the process() callback runs into a separate thread. What should I try?

Thanks,
Marco.
June 30, 2011
Marco Cosentino:

> Translated correctly the C callback style into D delegates types with alias.

D has function pointers too.


> Managed some segment faluts happened when not using toStringz() with some "strings"

For this kind of bugs I suggest to use the D type system in a smarter way. With extern you allowed to give what type you want to the C char* arguments, so you are free to use another type. An example:


import std.stdio: writeln;
import std.string: toStringz;

typedef const char* ccharPtr;

// example of C function, with smarter string type
extern(C) size_t strlen(ccharPtr str);

ccharPtr toStringz2(string s) {
    return cast(ccharPtr)toStringz(s);
}

void main() {
    string s1 = "this is ";
    string s2 = s1 ~ "just a string";
    writeln(s2.length);
    auto cs = toStringz2(s2);
    writeln(strlen(cs));
}


Now that typedef is deprecated what solution do you suggest instead?

Bye,
bearophile
June 30, 2011
Try this:

int
process (jack_nframes_t nframes, void *arg)

->

extern(C) int
process (jack_nframes_t nframes, void *arg)
June 30, 2011
Try this:

int
process (jack_nframes_t nframes, void *arg)

->

extern(C) int
process (jack_nframes_t nframes, void *arg)
July 01, 2011
On 01/07/2011 00:30, Andrej Mitrovic wrote:
> Try this:
>
> int
> process (jack_nframes_t nframes, void *arg)
>
> ->
>
> extern(C) int
> process (jack_nframes_t nframes, void *arg)

Thank you Andrej, that solved the problem!

Please can you biefly explain me what happens in the stack when calling that function with and without the "extern(C)" declaration?

I think that the D language would benefit from a deep, complete and open guide on how to _practically_ interface with C, accounting some popular designs cases not just a bunch of trivial cases like using 'printf' and a translation table of base types.

Marco
July 01, 2011
On 2011-07-01 11:13, Marco Cosentino wrote:
> On 01/07/2011 00:30, Andrej Mitrovic wrote:
>> Try this:
>>
>> int
>> process (jack_nframes_t nframes, void *arg)
>>
>> ->
>>
>> extern(C) int
>> process (jack_nframes_t nframes, void *arg)
>
> Thank you Andrej, that solved the problem!
>
> Please can you biefly explain me what happens in the stack when calling
> that function with and without the "extern(C)" declaration?
>
> I think that the D language would benefit from a deep, complete and open
> guide on how to _practically_ interface with C, accounting some popular
> designs cases not just a bunch of trivial cases like using 'printf' and
> a translation table of base types.
>
> Marco

What happens without "extern(C)" is that the function will use the D calling convention, with it, it will use the C calling convention. The C code your interfacing with excepts functions and function pointers with the C calling convention.

See:
http://www.digitalmars.com/d/2.0/interfaceToC.html
http://www.digitalmars.com/d/2.0/htomodule.html

-- 
/Jacob Carlborg
July 01, 2011
On 7/1/11, Marco Cosentino <cosentino.ma@gmail.com> wrote:
> On 01/07/2011 00:30, Andrej Mitrovic wrote:
>> Try this:
>>
>> int
>> process (jack_nframes_t nframes, void *arg)
>>
>> ->
>>
>> extern(C) int
>> process (jack_nframes_t nframes, void *arg)
>
> Thank you Andrej, that solved the problem!
>
> Please can you biefly explain me what happens in the stack when calling that function with and without the "extern(C)" declaration?
>
> I think that the D language would benefit from a deep, complete and open guide on how to _practically_ interface with C, accounting some popular designs cases not just a bunch of trivial cases like using 'printf' and a translation table of base types.
>
> Marco
>

This is a good start: http://en.wikipedia.org/wiki/Calling_convention