2009-10-30 39 views
3

我目前遇到了一個問題,同時玩弄Lua和外星人模塊以使用Win32 API等來自Lua腳本。到目前爲止,我只有一個關於使用API​​的外星人問題,使用某些結構,如CreateFontIndirect。Lua Alien - 調用特定的API

例如:

HFONT CreateFontIndirectA(const LOGFONT& lplf); 

LOGFONT:

typedef struct tagLOGFONT { 
LONG lfHeight; 
LONG lfWidth; 
LONG lfEscapement; 
LONG lfOrientation; 
LONG lfWeight; 
BYTE lfItalic; 
BYTE lfUnderline; 
BYTE lfStrikeOut; 
BYTE lfCharSet; 
BYTE lfOutPrecision; 
BYTE lfClipPrecision; 
BYTE lfQuality; 
BYTE lfPitchAndFamily; 
TCHAR lfFaceName[LF_FACESIZE]; 
}LOGFONT, *PLOGFONT; 

問題在於字體外觀名稱。我無法讓Lua在結構本身中保留一個字符串,它總是將一個指針放入結構中。所以我無法弄清楚,只能從Lua中使用這個API。

這是我得到的工作到一個點:

LOGFONT = alien.defstruct { 
    { 'lfHeight', 'long' }, 
    { 'lfWidth', 'long' }, 
    { 'lfEscapement', 'long' }, 
    { 'lfOrientation', 'long' }, 
    { 'lfWeight', 'long' }, 
    { 'lfItalic', 'byte' }, 
    { 'lfUnderline', 'byte' }, 
    { 'lfStrikeOut', 'byte' }, 
    { 'lfCharSet', 'byte' }, 
    { 'lfOutPrecision', 'byte' }, 
    { 'lfClipPrecision', 'byte' }, 
    { 'lfQuality', 'byte' }, 
    { 'lfPitchAndFamily', 'byte' }, 
    { 'lfFaceName', 'string' } -- This line isn't working properly. 
} 



gdi32 = alien.load("gdi32.dll") 
gdi32.CreateFontIndirectA:types { 
    ret = 'long', 
    abi = 'stdcall', 
    'pointer' 
} 

一個例子來調用它:

local lf = LOGFONT:new() 
lf.lfHeight = 14 
lf.lfWidth = 0 
lf.lfEscapement = 0 
lf.lfOrientation = 0 
lf.lfWeight = 400 
lf.lfItalic = 0 
lf.lfUnderline = 0 
lf.lfStrikeOut = 0 
lf.lfCharSet = 0 
lf.lfOutPrecision = 0 
lf.lfClipPrecision = 0 
lf.lfQuality = 0 
lf.lfPitchAndFamily = 0 
lf.lfFaceName = 'Terminal' 

local hFont = gdi32.CreateFontIndirectA(lf()) 

調試我的應用程序,它運行我的腳本顯示了API正確調用,除字體外,所有內容都正確傳遞。我試過各種不同的方法來使它工作,但我不能根據需要得到它。

有關修復這個問題的任何提示,而不用硬編碼其他任何東西到exe中?

回答

3

外星人的字符串類型僅用於指向字符串的指針,這就是爲什麼你的例子不工作。嘗試:

-- LF_FACESIZE = ? -- put the value of the LF_FACESIZE constant here 

LOGFONT = alien.defstruct { 
    { 'lfHeight', 'long' }, 
    { 'lfWidth', 'long' }, 
    { 'lfEscapement', 'long' }, 
    { 'lfOrientation', 'long' }, 
    { 'lfWeight', 'long' }, 
    { 'lfItalic', 'byte' }, 
    { 'lfUnderline', 'byte' }, 
    { 'lfStrikeOut', 'byte' }, 
    { 'lfCharSet', 'byte' }, 
    { 'lfOutPrecision', 'byte' }, 
    { 'lfClipPrecision', 'byte' }, 
    { 'lfQuality', 'byte' }, 
    { 'lfPitchAndFamily', 'byte' }, 
    { 'lfFaceName', 'char' } 
} 

LOGFONT.size = LOGFONT.size + LF_FACESIZE - 1 -- so Alien allocates enough space 
               -- for the whole array 

function get_lfname(lf) -- gets the lfFaceName field as a Lua string 
    local out = {} 
    local offset = LOGFONT.offsets.lfFaceName 
    local buf = lf() 
    for i = offset, offset+LF_FACESIZE-1 do 
    local c = buf:get(i, "char") 
    if c ~= 0 then 
     out[#out+1] = string.char(c) 
    else 
     break 
    end 
    end 
    return table.concat(out) 
end 

function set_lfname(lf, s) -- sets the Lua string s as the lfFaceName 
    local offset = LOGFONT.offsets.lfFaceName 
    local buf = lf() 
    for i = 1, LF_FACESIZE do 
    if i <= #s then 
     buf:set(offset+i, string.byte(string.sub(s, i, i)), "char") 
    else 
     buf:set(offset+i, 0, "char") 
     break 
    end 
    end 
end 

現在只要分配一個LOFGONF結構如常,但使用get_lfname和set_lfname功能與lfFaceName屬性的工作:

local lf = LOGFONT:new() 
lf.lfHeight = 14 
lf.lfWidth = 0 
lf.lfEscapement = 0 
lf.lfOrientation = 0 
lf.lfWeight = 400 
lf.lfItalic = 0 
lf.lfUnderline = 0 
lf.lfStrikeOut = 0 
lf.lfCharSet = 0 
lf.lfOutPrecision = 0 
lf.lfClipPrecision = 0 
lf.lfQuality = 0 
lf.lfPitchAndFamily = 0 
set_lfname(lf, 'Terminal') 

local hFont = gdi32.CreateFontIndirectA(lf()) 

搭接在端部的陣列是一種常見的圖案對於我忘記的C編程結構。我將在下一版的Alien中直接支持它。

-1

非常感謝mascarenhas,這個解決方案奏效。但是我必須調整你的set_lfname函數,因爲偏移量+ i-1未對齊,覆蓋了結構中的lfPitchAndFamily字節,刪除了-1,並且效果很好。 :)

+1

請在mascarenhas的回答下將其內容複製到評論後刪除該答案,然後接受答案(點擊左邊的複選標記)。 – 2009-11-05 03:33:25