Haskell Win32 LPCTSTR IsString类型类

时间:2018-12-17 13:44:21

标签: haskell

我正在测试incline-c的win32 api。 我意识到LPCTSTR没有IsString实例。 但是我不知道怎么写。 有提示吗?

有关信息:

type LPTSTR = Ptr TCHAR
type TCHAR = CWchar

System.Win32.Types中定义

newtype CWchar

Haskell type representing the C wchar_t type.

Constructors
CWchar Int32    

这是我的代码:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}

import Data.String
import qualified Language.C.Inline.Win32 as CW
import qualified Language.C.Inline as C
import System.Win32.Types

instance IsString LPCTSTR where


C.context CW.win32Ctx

C.include "<windows.h>"

showMsg :: LPCTSTR -> IO INT
showMsg s = do
  [C.exp| INT{ MessageBox( NULL, $(LPCTSTR s), "Haskell Rocks", MB_OK )} |]

main = showMsg "Hello Haskell"

编辑: 我设法用ByteString实现了这一点

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}

import qualified Data.ByteString as BS
import qualified Language.C.Inline.Win32 as CW
import qualified Language.C.Inline as C
import System.Win32.Types

C.context (CW.win32Ctx <> C.bsCtx)

C.include "<windows.h>"

showMsg :: BS.ByteString -> IO INT
showMsg s = do
  [C.exp| INT{ MessageBox( NULL, $bs-ptr:s, "Haskell Rocks", MB_OK )} |]

main = showMsg "Hello Haskell"

1 个答案:

答案 0 :(得分:4)

由于无法使用CString完成此实例,因此无法合理地定义此实例:指向char的指针不能执行内存管理。因此,在运行时生成C字符串对于悬挂内存是不安全的,否则会导致内存泄漏。

原则上应该可能的是尽管如此,仍然可以访问字符串文字,这在C本身中也是可行的:只需分配静态内存位置编译时间一次。但是IsString类不支持此功能。

总结:C字符串在Haskell中很难使用,因此最好仅在C代码的接口上直接使用它们。即如果您甚至使用C [w]字符串围绕C函数编写了低级包装,则应使用StringText作为参数。围绕C调用将其转换为IO块中合适的C字符串,并与unsafePerformIO一起“净化”它们。