How can I make this work?

Adam D. Ruppe destructionator at gmail.com
Sun Feb 28 13:15:47 UTC 2021


On Sunday, 28 February 2021 at 07:05:27 UTC, Jack wrote:
> I'm using a windows callback function where the user-defined 
> value is passed thought a LPARAM argument type. I'd like to 
> pass my D array then access it from that callback function. How 
> is the casting from LPARAM to my type array done in that case?

The best way to do this is to put the array inside a struct and 
pass the address of the struct instead. This way both length and 
pointer are passed, and you have the option to add more things if 
you ended up needing it later, and there's fewer weird things to 
worry about.

int[] arr = [1, 2, 3];

struct MyMessage {
      int[] arr;
}

// this far is easy enough
MyMessage* messagePointer = new MyMessage(arr);

// but we do need to tell the GC we intend to pass this to the 
outside world
// failure to do this MIGHT lead to random crashes as the GC 
can't see it (it can't look inside the Windows message queue), 
assumes it is unused, and frees it out from under you.
import core.memory;
GC.addRoot(messagePointer);

// when the GC has a root, it will consider that pointer live 
until further notice and not collect it nor its member variables.

// so it is now cool to do this
PostMessage(hwnd, MSG_WHATEVER, 0, cast(LPARAM) messagePointer);


/* then on the other side */

switch(iMsg) {
    case MSG_WHATEVER:
        MyMessage* messagePointer = cast(MyMessage*) lParam;

        // need to tell the GC the pointer can be automatically 
managed normally again. failure to do this will lead to a memory 
leak
        import core.memory;
        GC.removeRoot(messagePointer);

        // now can use it
        foreach(item; messagePointer.arr) {
           // yada yada yada
        }
}



And it is the simplest thing, no missing length, no weird 
property casting. The GC handled with two simple add/remove calls.


More information about the Digitalmars-d-learn mailing list