Quantcast

How do I marshall a pointer over SendMessage LPARAM or WPARAM?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

How do I marshall a pointer over SendMessage LPARAM or WPARAM?

Simon Peter Nicholls
Cross-posted from Haskell-beginners. Apologies for not posting in the
right place (though I am a beginner and have probably made a simpleton
error).

I'm new to Haskell, and have had some good success with FFI so far,
but using Win32's sendMessage to send a pointer in LPARAM or WPARAM is
resulting in access violations at the other end.

Is there some issue with my pointer conversions? Am I hitting some
restriction, or missing some compiler options?


 It's driving me pretty crazy, after a very nice start to using Haskell.

Some "sending" code:

            Foreign.C.String.withCWString "frustrator" $ \s -> do
                let wParam = System.Win32.Types.castPtrToUINT s ::
System.Win32.Types.WPARAM
                Graphics.Win32.sendMessage wnd Graphics.Win32.wM_APP wParam 0

wndProc "receiving" code:

    | wmsg == Graphics.Win32.wM_APP = do
        s <- peekCWString $ System.Win32.Types.castUINTToPtr wParam
        putStrLn s
        return 0

The string will not be seen.

Some extra notes:

I can get wndProc messages and integral data generally.
The pointer values match textually at both ends when "shown" to stdout.
At the sending side I can pass the CWString to a regular FFI function
call just fine, and castUINTToPtr will give me back a functioning Ptr
for that call.

 I have also tried sending to & receiving from a working C++ program,
without success. Access violations are reported when receiving, though
again the address matches up. Silence from Haskell as before, when C++
is sending.

I found someone else having an issue here:
http://osdir.com/ml/haskell-cafe@.../2009-11/msg00731.html but
no solution unfortunately.

UPDATE since prior posting:

Seems if I call out via FFI on the sending side, and set the WPARAM to
L"hardcoding FTW" in a wrapper C function, the SendMessage I then
invoke will work. The C code sees both the original string and the new
one, but only the second works when used.

I must be missing something obvious, but have toasted my grey cells at
this point!

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do I marshall a pointer over SendMessage LPARAM or WPARAM?

Yuras Shumovich
On Wed, 2012-07-18 at 18:22 +0200, Simon Peter Nicholls wrote:

> Some "sending" code:
>
>             Foreign.C.String.withCWString "frustrator" $ \s -> do
>                 let wParam = System.Win32.Types.castPtrToUINT s ::
> System.Win32.Types.WPARAM
>                 Graphics.Win32.sendMessage wnd Graphics.Win32.wM_APP wParam 0
>
> wndProc "receiving" code:
>
>     | wmsg == Graphics.Win32.wM_APP = do
>         s <- peekCWString $ System.Win32.Types.castUINTToPtr wParam
>         putStrLn s
>         return 0
>

From the docs
( http://hackage.haskell.org/packages/archive/base/4.5.1.0/doc/html/Foreign-C-String.html#v:withCWString ):

> the memory is freed when the subcomputation terminates (either
normally or via an exception), so the pointer to the temporary storage
must not be used after this

I'm noy a windows guru, but I assume that `sendMessage` just puts the
message into a queue and exits. So, you receive a pointer to already
deallocated memory.


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do I marshall a pointer over SendMessage LPARAM or WPARAM?

Simon Peter Nicholls
Sorry Yuras, I missed this.

It turns out that I made a mistake when trying to pinpoint my problem.
I had started out using WM_COPY_DATA and COPYDATASTRUCT, but upon
facing issues, tried simple sending of a C string and a WM_APP
message. However, that simplifying resulted in me losing the memory
mapping needed for copying data.

(for anyone facing similar woes)

The use of WM_COPY_DATA and COPYDATASTRUCT in combination are
essential, since Windows performs memory mapping to ensure the data
being "copied" is available to the receiving process:

WM_COPY_DATA message is received by Windows.
It's handled as a special case, and COPYDATASTRUCT is inspected.
cbData worth of bytes are memory mapped for the lpData content.
A WM_COPY_DATA message will be received in your wndProc function, with
an appropriate COPYDATASTRUCT for the memory mapped content.

It's fine to use withTString (and similar) in combination with
sendMessage, since the IO will be syncronous.

cbData for a TString can be calculated by string length * size of a
System.Win32.Types.TCHAR, accounting for end of string sentinel.

withTStringLen can also be used, but be aware that the zero terminator
will not be present, and I'm not sure if the "Len" given by that
function is string length, or byte count. I wanted a regular
terminated c string, and so haven't tried it.

On Wed, Jul 18, 2012 at 7:29 PM, Yuras Shumovich <[hidden email]> wrote:

> On Wed, 2012-07-18 at 18:22 +0200, Simon Peter Nicholls wrote:
>
>> Some "sending" code:
>>
>>             Foreign.C.String.withCWString "frustrator" $ \s -> do
>>                 let wParam = System.Win32.Types.castPtrToUINT s ::
>> System.Win32.Types.WPARAM
>>                 Graphics.Win32.sendMessage wnd Graphics.Win32.wM_APP wParam 0
>>
>> wndProc "receiving" code:
>>
>>     | wmsg == Graphics.Win32.wM_APP = do
>>         s <- peekCWString $ System.Win32.Types.castUINTToPtr wParam
>>         putStrLn s
>>         return 0
>>
>
> From the docs
> ( http://hackage.haskell.org/packages/archive/base/4.5.1.0/doc/html/Foreign-C-String.html#v:withCWString ):
>
>> the memory is freed when the subcomputation terminates (either
> normally or via an exception), so the pointer to the temporary storage
> must not be used after this
>
> I'm noy a windows guru, but I assume that `sendMessage` just puts the
> message into a queue and exits. So, you receive a pointer to already
> deallocated memory.
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Loading...