2009-10-30 75 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