
Hi, The following code works:
type ServiceMainClosure = DWORD -> IO ()
foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)
But the following doesn't:
type ServiceMainClosure = DWORD -> [String] -> IO ()
foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)
System\Win32\Service.hsc:108:8: parse error on input `import' What can I do to get this to work? Thanks -John

On Tue, Feb 06, 2007 at 12:33:58PM +1100, John Ky wrote:
Hi,
The following code works:
type ServiceMainClosure = DWORD -> IO ()
foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)
But the following doesn't:
type ServiceMainClosure = DWORD -> [String] -> IO ()
foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)
System\Win32\Service.hsc:108:8: parse error on input `import'
What can I do to get this to work?
You have to use a type that C's tiny brain understains. IANAWP but I'm guessing you want: type ServiceMainClosure = DWORD -> Ptr (Ptr CChar) -> IO () foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)

Hi Stefan,
In that case, how do I marshall [String] to Ptr (Ptr CChar)?
Thanks
-John
On 2/6/07, Stefan O'Rear
You have to use a type that C's tiny brain understains. IANAWP but I'm guessing you want:
type ServiceMainClosure = DWORD -> Ptr (Ptr CChar) -> IO ()
foreign import ccall "wrapper" mkServiceMainClosure :: ServiceMainClosure -> IO (FunPtr ServiceMainClosure)

Actually, what I need to do is a fair bit more complex than string
marshalling. It feels like I'll need to pull together a number of different
concepts so I may as well describe the problem directly.
The C function I want to call is StartServiceCtrlDispatcher:
*BOOL* *StartServiceCtrlDispatcher(*
*const LPSERVICE_TABLE_ENTRY* *lpServiceTable**
**);*
It takes an array of SERVICE_TABLE_ENTRY structures:
typedef struct _SERVICE_TABLE_ENTRY {
LPTSTR lpServiceName;
LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY,
*LPSERVICE_TABLE_ENTRY;
The typedef LPSERVICE_MAIN_FUNCTION is something like:
*typedef (VOID WINAPI* *ServiceMain)(*
*DWORD* *dwArgc**,
* *LPTSTR** *lpszArgv**
**);*
It seems to me that I'll need to learn how to do the following:
* Represent SERVICE_TABLE_ENTRY AND LPSERVICE_TABLE_ENTRY structs as a
haskell type.
* Create an array of SERVICE_TABLE_ENTRY structs.
* Populate the array (they're null terminated).
* Do all sorts of elaborate marshalling so that the end product is a
sensibly typed Haskell function like this:
data ServiceTableEntry = ServiceTableEntry {
serviceName :: String
serviceProc :: [String] -> IO ()
}
startServiceCtrlDispatcher :: [ServiceTableEntry] -> IO ()
That's quite a lot to chew on and I finding it challenging learning about
all these things and combining them at the same time.
I've attached the complete source to what I have so far in a zip file.
Thanks
-John
On 2/6/07, Stefan O'Rear
On Tue, Feb 06, 2007 at 12:40:38PM +1100, John Ky wrote:
Hi Stefan,
In that case, how do I marshall [String] to Ptr (Ptr CChar)?
look at Foreign.C.String and Foreign.Ptr
participants (2)
-
John Ky
-
Stefan O'Rear