www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Interfacing with C; pointer to struct vs. class instance

reply "Arve Knudsen" <aknuds-1 broadpark.no> writes:
Forgive me if this is answered before or I'm missing something obvious.  
Can someone tell my why passing a pointer (&) to a class instance through  
a C library as void * and back to D produces such unexpected results? That  
is, I register a (extern (C)) callback and associated data (void pointer  
to my class instance), and when I in my callback cast back to MyClass *  
the object seems somehow modified. The pointer address is the same, but  
the addresses of the members are rubbish (accessing their members in turn  
causes segfault). This does *not* happen if I use struct instances  
instead, then it works as one would expect. Can someone enlighten me as to  
what is going on here? I found that it is safe to pass the object  
reference (as opposed to the address) to the C library, but I'd still like  
to know what happens.

Thanks

Arve Knudsen
Jul 13 2005
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Arve Knudsen" <aknuds-1 broadpark.no> wrote in message 
news:op.stutd0gyfmr65f localhost...
 Forgive me if this is answered before or I'm missing something obvious. 
 Can someone tell my why passing a pointer (&) to a class instance through 
 a C library as void * and back to D produces such unexpected results? That 
 is, I register a (extern (C)) callback and associated data (void pointer 
 to my class instance), and when I in my callback cast back to MyClass * 
 the object seems somehow modified. The pointer address is the same, but 
 the addresses of the members are rubbish (accessing their members in turn 
 causes segfault). This does *not* happen if I use struct instances 
 instead, then it works as one would expect. Can someone enlighten me as to 
 what is going on here? I found that it is safe to pass the object 
 reference (as opposed to the address) to the C library, but I'd still like 
 to know what happens.

 Thanks

 Arve Knudsen

Here's a stab in the dark: in D classes are manipulated by reference so MyClass* in D is like MyStruct** or in C++ MyClass**. A concrete code example would help us help you.
Jul 13 2005
parent "Arve Knudsen" <aknuds-1 broadpark.no> writes:
Hi, Ben

On Wed, 13 Jul 2005 15:55:17 +0200, Ben Hinkle <bhinkle mathworks.com>  
wrote:

 "Arve Knudsen" <aknuds-1 broadpark.no> wrote in message
 news:op.stutd0gyfmr65f localhost...
 Forgive me if this is answered before or I'm missing something obvious.
 Can someone tell my why passing a pointer (&) to a class instance  
 through
 a C library as void * and back to D produces such unexpected results?  
 That
 is, I register a (extern (C)) callback and associated data (void pointer
 to my class instance), and when I in my callback cast back to MyClass *
 the object seems somehow modified. The pointer address is the same, but
 the addresses of the members are rubbish (accessing their members in  
 turn
 causes segfault). This does *not* happen if I use struct instances
 instead, then it works as one would expect. Can someone enlighten me as  
 to
 what is going on here? I found that it is safe to pass the object
 reference (as opposed to the address) to the C library, but I'd still  
 like
 to know what happens.

 Thanks

 Arve Knudsen

Here's a stab in the dark: in D classes are manipulated by reference so MyClass* in D is like MyStruct** or in C++ MyClass**. A concrete code example would help us help you.

I suspect it may have to do with some kind of indirection (a reference is really a pointer under the hood), but I can't really visualize what happens. Anyway what I do is something like this: class MyClass { int x; } extern (C) void callback(void *data) { MyClass *obj = cast(MyClass *)(data); printf("%d\n", obj.x); } void myFunc() { MyClass obj = new MyClass(); registerCallback(&callback, &obj); } This is just a contrived example, but it should showcase the program flow. I see now that there's no reason to pass a D pointer to the C function, but it left me puzzled for a while. Arve
Jul 13 2005
prev sibling parent reply Mike Capp <mike.capp gmail.com> writes:
In article <op.stutd0gyfmr65f localhost>, Arve Knudsen says...
I register a (extern (C)) callback and associated data (void pointer  
to my class instance), and when I in my callback cast back to MyClass *  
the object seems somehow modified.

There may be other issues, but in the general case this is not a safe thing to do. D's garbage collector can and will move heap-allocated objects in memory when it runs. In fact it says explicitly in the "Types" docs: "Casting pointers to non-pointers and vice versa is allowed in D, however, do not do this for any pointers that point to data allocated by the garbage collector." cheers, Mike
Jul 13 2005
parent "Arve Knudsen" <aknuds-1 broadpark.no> writes:
Hi, Mike

On Wed, 13 Jul 2005 18:46:20 +0200, Mike Capp <mike.capp gmail.com> wrote:

 In article <op.stutd0gyfmr65f localhost>, Arve Knudsen says...
 I register a (extern (C)) callback and associated data (void pointer
 to my class instance), and when I in my callback cast back to MyClass *
 the object seems somehow modified.

There may be other issues, but in the general case this is not a safe thing to do. D's garbage collector can and will move heap-allocated objects in memory when it runs. In fact it says explicitly in the "Types" docs: "Casting pointers to non-pointers and vice versa is allowed in D, however, do not do this for any pointers that point to data allocated by the garbage collector."

Actually I explicitly defined allocation/deallocation methods for this class, so the GC wasn't involved (directly at least). Arve
Jul 13 2005