Thread overview
Interfacing with C; pointer to struct vs. class instance
Jul 13, 2005
Arve Knudsen
Jul 13, 2005
Ben Hinkle
Jul 13, 2005
Arve Knudsen
Jul 13, 2005
Mike Capp
Jul 13, 2005
Arve Knudsen
July 13, 2005
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
July 13, 2005
"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.


July 13, 2005
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


July 13, 2005
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
July 13, 2005
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