Haskell から wxWidgets の wxDateTime を使う

Haskell から wxWidgets の COM を使う場合、データは wxVaritant 型でやりとりします。
wxVaritant はあらゆる型のデータを格納可能で wxDateTime もそのひとつです。
分かりにくいのですが、やりたいことは HaskellVB のように Excel を読み書きしたり、AccessSQLserver にアクセスしたい訳です。

{-# LANGUAGE ForeignFunctionInterface #-}

module Main  where

import Foreign.Ptr           (Ptr)
import Foreign.C.String      (CWString, peekCWString)
import Foreign.C.Types       (CInt, CUShort)
import Foreign.Marshal.Alloc (free)

data WxString     = WxString
data WxDateTime   = WxDateTime

type WxStringObj  = Ptr WxString
type WxDTimeObj   = Ptr WxDateTime

main = do 
    today <- c_wxDateTimeToday
    putStrLn =<< wxToDateTimeString today  -- => 2011-01-12 00:00:00
    c_destroyWxDateTime today

    now   <- c_wxDateTimeNow
    putStrLn =<< wxToDateTimeString now    -- => 2011-01-12 11:54:12
    c_destroyWxDateTime now

    time <- createWxDateTime 1999 12 31  12 34 56
    putStrLn =<< wxToDateTimeString time   -- => 1999-12-31 12:34:56

    year   <- wxDateTimeGetYear   time
    month  <- wxDateTimeGetMonth  time
    day    <- wxDateTimeGetDay    time
    hour   <- wxDateTimeGetHour   time
    minute <- wxDateTimeGetMinute time
    second <- wxDateTimeGetSecond time
    c_destroyWxDateTime time

    putStrLn $ concat ["year:" ,show year," month:",show month," day:", show day,
                       " hour:",show hour," minute:", show minute," second:",show second]
    -- => year:1999 month:12 day:31 hour:12 minute:34 second:56

createWxDateTime :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> IO WxDTimeObj
createWxDateTime year month day hour minute second =
    c_newWxDateTime (fromIntegral  day) 
                    ((fromIntegral month)-1)
                    (fromIntegral  year)
                    (fromIntegral  hour)
                    (fromIntegral  minute)
                    (fromIntegral  second)

wxToDateTimeString :: WxDTimeObj -> IO String
wxToDateTimeString datetime = do
    dt <- wxDateTimeToDateString datetime
    tm <- wxDateTimeToTimeString datetime
    return $ dt ++ " " ++ tm

wxDateTimeToDateString :: WxDTimeObj -> IO String
wxDateTimeToDateString datetime = do
    wxStr    <- c_wxDateTimeFormatISODate datetime
    cwstring <- c_wxStringToCWString wxStr
    string   <- peekCWString cwstring
    c_destroyWxString wxStr
    free cwstring
    return  string

wxDateTimeToTimeString :: WxDTimeObj -> IO String
wxDateTimeToTimeString datetime =
    wxDateTimeToString c_wxDateTimeFormatISOTime datetime

wxDateTimeToString :: (WxDTimeObj -> IO WxStringObj) -> WxDTimeObj -> IO String
wxDateTimeToString func datetime = do
    wxStr    <- func datetime
    cwstring <- c_wxStringToCWString wxStr
    string   <- peekCWString cwstring
    c_destroyWxString wxStr
    free cwstring
    return  string

wxDateTimeGet :: (Integral t1) => (WxDTimeObj -> IO t1) -> WxDTimeObj -> IO Integer
wxDateTimeGet func dt = do
    cushort <- func dt
    return $ fromIntegral cushort

wxDateTimeGetYear :: WxDTimeObj -> IO Integer
wxDateTimeGetYear dt = wxDateTimeGet c_wxDateTimeGetYear dt

wxDateTimeGetMonth :: WxDTimeObj -> IO Integer
wxDateTimeGetMonth dt = wxDateTimeGet c_wxDateTimeGetMonth dt

wxDateTimeGetDay :: WxDTimeObj -> IO Integer
wxDateTimeGetDay dt = wxDateTimeGet c_wxDateTimeGetDay dt

wxDateTimeGetHour :: WxDTimeObj -> IO Integer
wxDateTimeGetHour dt = wxDateTimeGet c_wxDateTimeGetHour dt

wxDateTimeGetMinute :: WxDTimeObj -> IO Integer
wxDateTimeGetMinute dt = wxDateTimeGet c_wxDateTimeGetMinute dt

wxDateTimeGetSecond :: WxDTimeObj -> IO Integer
wxDateTimeGetSecond dt = wxDateTimeGet c_wxDateTimeGetSecond dt


-- wxDateTime
foreign import ccall unsafe "wxDateTimeToday"     c_wxDateTimeToday         :: IO WxDTimeObj
foreign import ccall unsafe "wxDateTimeNow"       c_wxDateTimeNow           :: IO WxDTimeObj
foreign import ccall unsafe "newWxDateTime"       c_newWxDateTime 
                 :: CUShort -> CInt -> CInt -> CUShort -> CUShort -> CUShort -> IO WxDTimeObj
foreign import ccall unsafe "destroyWxDateTime"        c_destroyWxDateTime        :: WxDTimeObj -> IO () 

foreign import ccall unsafe "wxDateTimeFormatISODate"  c_wxDateTimeFormatISODate :: WxDTimeObj -> IO WxStringObj
foreign import ccall unsafe "wxDateTimeFormatISOTime"  c_wxDateTimeFormatISOTime :: WxDTimeObj -> IO WxStringObj
foreign import ccall unsafe "wxDateTimeGetYear"        c_wxDateTimeGetYear       :: WxDTimeObj -> IO CInt
foreign import ccall unsafe "wxDateTimeGetMonth"       c_wxDateTimeGetMonth      :: WxDTimeObj -> IO CInt
foreign import ccall unsafe "wxDateTimeGetDay"         c_wxDateTimeGetDay        :: WxDTimeObj -> IO CUShort
foreign import ccall unsafe "wxDateTimeGetHour"        c_wxDateTimeGetHour       :: WxDTimeObj -> IO CUShort
foreign import ccall unsafe "wxDateTimeGetMinute"      c_wxDateTimeGetMinute     :: WxDTimeObj -> IO CUShort
foreign import ccall unsafe "wxDateTimeGetSecond"      c_wxDateTimeGetSecond     :: WxDTimeObj -> IO CUShort

-- wxString ------------------
foreign import ccall  unsafe   "createWxString"      c_createWxString      :: CWString    -> IO WxStringObj
foreign import ccall  unsafe   "wxStringToCWString"  c_wxStringToCWString  :: WxStringObj -> IO CWString
foreign import ccall  unsafe   "destroyWxString"     c_destroyWxString     :: WxStringObj -> IO()
#include <stdio.h>
#include <stdlib.h>
#include <locale.h >
#include <wx/wx.h>
#include <wx/string.h>
#include <wx/datetime.h>

extern "C" {

// ---------------- wxDateTime ------------------
wxDateTime* wxDateTimeToday(){
    wxDateTime *ret = new wxDateTime();
    *ret = wxDateTime::Today();
    return ret;
}

wxDateTime* wxDateTimeNow(){
    wxDateTime *ret = new wxDateTime();
    *ret = wxDateTime::Now();
    return ret;
}

wxDateTime* newWxDateTime( unsigned short day,  int month,             int year,
                           unsigned short hour, unsigned short minute, unsigned short second){
                                                                                                  // millisec
    wxDateTime *ret = new wxDateTime( day, (wxDateTime::Month) month, year, hour, minute, second, 0);
    return ret;
}

void destroyWxDateTime(wxDateTime* dt){ delete dt;}

// This function returns the date representation in the ISO 8601 format (YYYY-MM-DD).
wxString* wxDateTimeFormatISODate(wxDateTime* dt){
    wxString *ret = new wxString();
    *ret = dt->FormatISODate();
    return ret;
}

// This function returns the time representation in the ISO 8601 format (HH:MM:SS).
wxString* wxDateTimeFormatISOTime(wxDateTime* dt){
    wxString *ret = new wxString();
    *ret = dt->FormatISOTime();
    return ret;
}

int wxDateTimeGetYear(wxDateTime* dt){ return dt->GetYear();}
int wxDateTimeGetMonth(wxDateTime* dt){ return (int)(dt->GetMonth());}
unsigned short wxDateTimeGetDay(wxDateTime* dt){ return dt->GetDay();}
unsigned short wxDateTimeGetHour(wxDateTime* dt){ return dt->GetHour();}
unsigned short wxDateTimeGetMinute(wxDateTime* dt){ return dt->GetMinute();}
unsigned short wxDateTimeGetSecond(wxDateTime* dt){ return dt->GetSecond();}

// ---------------- wxString ----------------
wxString* createWxString(wchar_t* wstring){
    return new wxString(wstring);
}

void destroyWxString(wxString* str){ delete str;}

wchar_t* wxStringToCWString(wxString* str){
    wchar_t *wstring  = (wchar_t*)malloc((str->length() +1) * sizeof(wchar_t));
    wcscpy( wstring, (wchar_t*)str->wchar_str()); 
    return wstring;
}

}
g++ WxDateTime.cpp -c `wx-config --cxxflags` -o wxdatetime.o

ghc --make DateTime.hs wxdatetime.o \
-DHAVE_W32API_H -D__WXMSW__ -D_UNICODE \
-I/c/msys/1.0/home/userName/wxMSW-2.8.11/lib/gcc_dll/mswu \
-I/c/msys/1.0/home/userName/wxMSW-2.8.11/include \
-DWXUSINGDLL \
-L/c/msys/1.0/home/userName/wxMSW-2.8.11/lib/gcc_dll \
-L/c/MinGW/lib \
-lstdc++  \
-lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu \
-lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwxregexu \
-lwinspool -lwinmm -lshell32 -lcomctl32 -lole32 -loleaut32 \
-luuid -lodbc32 -lodbccp32 -lrpcrt4 -ladvapi32 -lwsock32 -lwxmsw28u -o dt.exe