【问题标题】:Lua Alien - Calling Specific APILua Alien - 调用特定 API
【发布时间】:2009-10-30 03:56:31
【问题描述】:

我目前在玩 Lua 和外星人模块以使用 Lua 脚本中的 Win32 API 等时遇到了一个问题。到目前为止,我只遇到过外星人的一个问题,即使用使用某些结构(如 CreateFontIndirect)的 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 中的情况下解决此问题的任何提示?

【问题讨论】:

    标签: winapi api lua


    【解决方案1】:

    Alien 的字符串类型仅用于指向字符串的指针,这就是您的示例不起作用的原因。试试这个:

    -- 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 中直接支持它。

    【讨论】:

      【解决方案2】:

      非常感谢 mascarenhas 的回复,这个解决方案奏效了。不过,我确实必须调整您的 set_lfname 函数,因为 offset+i-1 未对齐并覆盖结构中的 lfPitchAndFamily 字节,删除了 -1 并且效果很好。 :)

      【讨论】:

      • 请将其内容复制到 mascarenhas 答案下的评论后删除此答案,然后接受该答案(单击其左侧的复选标记)。
      猜你喜欢
      • 1970-01-01
      • 2015-07-04
      • 2013-05-31
      • 2017-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      相关资源
      最近更新 更多