Re: How can I make this work?

2021-03-16 Thread Jack via Digitalmars-d-learn

On Tuesday, 16 March 2021 at 16:02:14 UTC, Vinod K Chandran wrote:
On Sunday, 28 February 2021 at 13:15:47 UTC, Adam D. Ruppe 
wrote:


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


Perfect example of teaching something. Thank you for this 
knowledge. Even though, this was not my problem, Its really 
helpful for me to my future project. :)


elegant approach


Re: How can I make this work?

2021-03-16 Thread Vinod K Chandran via Digitalmars-d-learn

On Sunday, 28 February 2021 at 13:15:47 UTC, Adam D. Ruppe wrote:


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


Perfect example of teaching something. Thank you for this 
knowledge. Even though, this was not my problem, Its really 
helpful for me to my future project. :)





Re: How can I make this work?

2021-03-16 Thread Jack via Digitalmars-d-learn

On Sunday, 28 February 2021 at 13:15:47 UTC, Adam D. Ruppe wrote:

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.


This is what I ended up using. using a single pointer such as 
MyMessage makes things much simpler. Thanks for the rememinder of 
GC.removeRoot()


Everyone else in this theread, thank you guys. Always helpful


Re: How can I make this work?

2021-02-28 Thread Adam D. Ruppe via Digitalmars-d-learn

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.


Re: How can I make this work?

2021-02-28 Thread rikki cattermole via Digitalmars-d-learn

On 28/02/2021 11:05 PM, Max Haughton wrote:

Do the windows APIs expect the length in memory rather than as a parameter?


This sounds like its being sent via a user field to be passed to a callback.

I.e. event loop for a window.

In this sort of case you only get one parameter on the callback and it 
is only big enough for a pointer.


Re: How can I make this work?

2021-02-28 Thread Max Haughton via Digitalmars-d-learn

On Sunday, 28 February 2021 at 09:18:56 UTC, Rumbu wrote:

On Sunday, 28 February 2021 at 09:04:49 UTC, Rumbu wrote:

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?


for example, I need something like this to work:

int[] arr = [1, 2, 3];
long l = cast(long) cast(void*) arr.ptr;
int[] a = cast(int[]) cast(void*) l;


LPARAM is not long on 32 bits, it's int. Use LPARAM instead of 
long.


And you are passing only the address of the first element this 
way, loosing the array/slice length. This should work, but keep 
in mind that you have no warranty that the array stays in 
memory and it is not garbage collected.


int[] arr = [1, 2, 3];
LPARAM l = cast(LPARAM)cast(void*)
int[] a = *cast(int[]*)(cast(void*)l);


Do the windows APIs expect the length in memory rather than as a 
parameter?


Also Rumbu can you check your email - I may have emailed you on 
an old email address by accident, but it's about the blog and it 
will be from mh240@...


Re: How can I make this work?

2021-02-28 Thread Rumbu via Digitalmars-d-learn

On Sunday, 28 February 2021 at 09:04:49 UTC, Rumbu wrote:

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?


for example, I need something like this to work:

int[] arr = [1, 2, 3];
long l = cast(long) cast(void*) arr.ptr;
int[] a = cast(int[]) cast(void*) l;


LPARAM is not long on 32 bits, it's int. Use LPARAM instead of 
long.


And you are passing only the address of the first element this 
way, loosing the array/slice length. This should work, but keep 
in mind that you have no warranty that the array stays in memory 
and it is not garbage collected.


int[] arr = [1, 2, 3];
LPARAM l = cast(LPARAM)cast(void*)
int[] a = *cast(int[]*)(cast(void*)l);




Re: How can I make this work?

2021-02-28 Thread Rumbu via Digitalmars-d-learn

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?


for example, I need something like this to work:

int[] arr = [1, 2, 3];
long l = cast(long) cast(void*) arr.ptr;
int[] a = cast(int[]) cast(void*) l;


LPARAM is not long on 32 bits, it's int. Use LPARAM instead of 
long.




Re: How can I make this work?

2021-02-28 Thread rikki cattermole via Digitalmars-d-learn

On 28/02/2021 8:05 PM, Jack wrote:

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

size_t l = cast(size_t)arr.ptr;

Okay, so far so good


int[] a = cast(int[]) cast(void*) l;


Umm, you haven't specified a length?

int[] a = (cast(int*)l)[0 .. 3];

If the callback is being called (in effect under the current stack frame 
and won't escape), I would wrap the data you need in a struct and pass 
that to it instead by pointer. No need for heap allocation and gives a 
way to pass more complex data should the need arise.


Re: How can I make this work?

2021-02-27 Thread evilrat via Digitalmars-d-learn

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?


for example, I need something like this to work:

int[] arr = [1, 2, 3];
long l = cast(long) cast(void*) arr.ptr;
int[] a = cast(int[]) cast(void*) l;


Should already work like that. Just be aware that array can be 
garbage collected if no references for it are kept somewhere else 
between set callback and the actual call, otherwise you can get 
some random garbage.


Also be aware that such casts 99% basically a speculation, there 
is no guarantee that returned data is actually an int[].