www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C callback receives bad pointer argument

reply Marco Cosentino <cosentino.ma gmail.com> writes:
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.
Jun 30 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
Jun 30 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Try this:

int
process (jack_nframes_t nframes, void *arg)

->

extern(C) int
process (jack_nframes_t nframes, void *arg)
Jun 30 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Try this:

int
process (jack_nframes_t nframes, void *arg)

->

extern(C) int
process (jack_nframes_t nframes, void *arg)
Jun 30 2011
parent reply Marco Cosentino <cosentino.ma gmail.com> writes:
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
Jul 01 2011
next sibling parent Jacob Carlborg <doob me.com> writes:
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
Jul 01 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
Jul 01 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
 Now that typedef is deprecated what solution do you suggest instead?
Something like this, I think: struct ccharPtr { const char* ptr; alias ptr this; } ccharPtr toStringz2(string s) { return ccharPtr(toStringz(s)); } Bye, bearophile
Jun 30 2011