[Haskell-cafe] Why am I not allowed to use CStringLen inforeignexport?

Andreas Marth Andreas-Haskell at gmx.net
Fri Sep 22 03:53:19 EDT 2006


Thanks a lot for this information it helped a lot.
Because I use the VBA 6 version the string characters are supposed to be a
byte so I changed your code to

type BSTR8 = Ptr Word8

createBSTR8 :: String -> IO BSTR8
createBSTR8 s = do
   let
     len :: Word32 = fromIntegral (length s)
     low_l :: Word8 = fromIntegral (len .&. 0xFFFF)
     low_h :: Word8 = fromIntegral (shiftR len 8 .&. 0xFFFF)
     high_l :: Word8 = fromIntegral (shiftR len 16 .&. 0xFFFF)
     high_h :: Word8 = fromIntegral (shiftR len 24 .&. 0xFFFF)
   arr <- newArray ([low_l,low_h,high_l,high_h] ++ map (fromIntegral .
fromEnum) s ++ [0])
   return $! plusPtr arr 4

Maybe this helps some one else too.
I am thinking about creating a wikipage about Haskell<->VBA interfacing
through a DLL.
Is it okay for you if I put your code there?
I am a bit concerned about the memory. newArray states that the memory has
to be freed after usage. Is this needed here? How can it be done?

Thanks to everyone who responded,
Andreas



----- Original Message -----
From: "Brian Hulley" <brianh at metamilk.com>
To: "Andreas Marth" <Andreas-Haskell at gmx.net>; <haskell-cafe at haskell.org>
Sent: Friday, September 15, 2006 10:07 PM
Subject: Re: [Haskell-cafe] Why am I not allowed to use CStringLen
inforeignexport?


> Brian Hulley wrote:
> > I assume that this means that on 32 bit Windows, the format of a BSTR
> > is:
> >     Word16 -- low word of length
> >     Word16 -- high word of length
> >     Word16 -- first char of string
> >      ...
>
> The above is not quite correct. It appears from
> http://www.oreilly.com/catalog/win32api/chapter/ch06.html that the length
> must preceed the actual BSTR, thus you must give VBA a pointer to the
first
> *char* in the string not the actual start of the array of Word16's in
> memory. Furthermore, it appears that a terminating NULL is still needed
even
> though the string itself can contain NULL characters. No only that, but
the
> length must be given as the number of *bytes* (excluding the terminating
> NULL) not the number of characters.
>
> Therefore here is a revised attempt at creating a Win32 BSTR:
>
>     import Data.Word
>     import Data.Bits
>     import Foreign.Marshal.Array
>     import Foreign.Ptr
>
>     type BSTR = Ptr Word16
>
>     createBSTR :: [Char] -> IO BSTR
>     createBSTR s = do
>         let
>             len :: Word32 = fromIntegral (length s * 2)
>             low :: Word16 = fromIntegral (len .&. 0xFFFF)
>             high :: Word16 = fromIntegral (shiftR len 16 .&. 0xFFFF)
>         arr <- newArray ([low, high] ++ map (fromIntegral . fromEnum) s ++
> [0])
>         return $! plusPtr arr 4
>
>     foreign export stdcall hello :: IO BSTR
>     hello :: IO BSTR
>     hello = createBSTR "Hello world!"
>
> Regards, Brian.
>



More information about the Haskell-Cafe mailing list