2014-05-05 15 views
5

Tôi đang cố gắng viết các ràng buộc với một số hàm win32 API không có trong gói win32, nhưng chạy vào một chút khó khăn. Trong đoạn mã sau các ràng buộc cho EnumWindows và làm việc tốt GetWindow, nhưng những người cho GetWindowText và GetWindowTextLength không:Haskell tham chiếu không xác định khi gọi một số chức năng win32 api

{-# LANGUAGE ForeignFunctionInterface #-} 

import Foreign.Ptr 
import Graphics.Win32.GDI.Types (HWND) 
import System.Win32.Types (ptrToMaybe) 
import Foreign.C 
import Foreign.Marshal.Alloc (free) 
import Control.Applicative ((<$>)) 

gW_CHILD = 5::CInt 

getWindow :: HWND -> CInt -> IO (Maybe HWND) 
getWindow hwnd cint = ptrToMaybe <$> (c_getWindow hwnd cint) 
foreign import stdcall "windows.h GetWindow" 
    c_getWindow :: HWND -> CInt -> IO HWND 

foreign import stdcall "windows.h EnumWindows" 
    enumWindows :: (FunPtr (HWND -> Ptr b -> IO a)) -> CInt -> IO CInt 

foreign import stdcall "windows.h GetWindowText" 
    getWindowText :: HWND -> CString -> CInt -> IO CInt 

foreign import stdcall "windows.h GetWindowTextLength" 
    getWindowTextLength :: HWND -> IO CInt 

foreign import ccall "wrapper" 
    wrapEnumWindowsProc :: (HWND -> Ptr a -> IO CInt) -> IO (FunPtr (HWND -> Ptr a-> IO CInt)) 

findFirstNamedChildWindow :: HWND -> Ptr a -> IO CInt 
findFirstNamedChildWindow hwnd _ = do 
     mchild <- getWindow hwnd gW_CHILD 
     case mchild of 
      Just hchwnd -> do     
        clen <- getWindowTextLength (hchwnd) 
        case clen of 
         0 -> return 1 
         _ -> do 
           str <- newCString (replicate (fromEnum clen) ' ') 
           getWindowText hwnd str $ clen+1 
           print =<< peekCString str 
           free str >> return 0           
      Nothing -> return 1 
main = do 
     enptr <- wrapEnumWindowsProc findFirstNamedChildWindow 
     enumWindows enptr 0 
     return() 

tôi nhận được thông báo lỗi sau:

C:\Users\me>ghc nc.hs 
Linking nc.exe ... 
nc.o:fake:(.text+0x958): undefined reference to `[email protected]' 
nc.o:fake:(.text+0xe12): undefined reference to `[email protected]' 
collect2: ld returned 1 exit status 

Tất cả 4 chức năng đang trong User32 .dll. Phiên bản GHC là 7.8.2 (32 bit), hệ điều hành là Windows 7 (64).

Nếu tôi thêm C tập tin này:

#include <windows.h> 

int getWindowText (HWND hwnd, char* str, int len) { 
    return GetWindowText (hwnd, str, len); 
    } 
int getWindowTextLength (HWND hwnd) { 
    return GetWindowTextLength (hwnd); 
    } 

và thay đổi khẩu gọi

foreign import call "getWindowText" 

foreign import call "getWindowTextLength" 

mọi thứ hoạt động như mong đợi. Điều gì đang xảy ra? Một cái gì đó về phôi tiềm ẩn hoặc một cái gì đó như thế? Tôi đã thử các chức năng chuỗi rộng từ Foreign.C.String nhưng điều đó không thay đổi bất cứ điều gì. (Ngoài ra là cách dự định để vượt qua một bộ đệm chuỗi cho C để ghi vào hoặc là có một phương pháp tốt hơn?)

Trả lời

9

Hầu hết các chức năng Windows xử lý chuỗi có hai phiên bản, một phiên bản ANSI với hậu tố A và Unicode phiên bản có hậu tố W. Ví dụ: GetWindowText thực sự được xuất dưới dạng hai hàm, GetWindowTextAGetWindowTextW. Những tên này xuất hiện gần bottom of the documentation.

Thông số LPTSTR được hiểu là LPSTR cho phiên bản ALPWSTR cho phiên bản W. Bạn có thể sử dụng một trong hai chức năng, nhưng rõ ràng bạn phải sử dụng loại chuỗi thích hợp để đi với nó.

Phiên bản C hoạt động vì GetWindowText thực sự là macro C mở rộng đến GetWindowTextA hoặc GetWindowTextW tùy thuộc vào việc bạn đã xác định macro UNICODE hay chưa.

+1

Cảm ơn, 'ngoại nhập stdcall" windows.h GetWindowTextLengthA "' hoạt động tốt. –

Các vấn đề liên quan