Lua Alien - 调用特定的 API [英] Lua Alien - Calling Specific API

查看:13
本文介绍了Lua Alien - 调用特定的 API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在玩弄 Lua 和外星人模块以使用 Lua 脚本中的 Win32 API 等时遇到了一个问题.到目前为止,我只遇到了一个关于 Alien 的问题,即使用使用某些结构(例如 CreateFontIndirect)的 API.

I have currently run into an issue while toying with Lua and the alien module to use Win32 API and such from Lua scripts. So far I have only had a single issue with alien which is with the use of API that use certain structures such as CreateFontIndirect.

例如:

HFONT CreateFontIndirectA( const LOGFONT& lplf );

登录字体:

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.

The issue lies with the font face name. I cannot get Lua to keep a string inside the structure itself, it always pushes a pointer into the structure. So there is no way, that I can figure out, to be able to use this API purely from Lua.

这就是我的工作重点:

 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 被正确调用,除了字体外,所有内容都正确传递.我尝试了各种不同的方法来让它工作,但我无法按需要让它运行.

Debugging my application that runs my script shows that the api is being called properly, everything is passed properly except the font face. I've tried various different methods to get it working but I cant get it to go as needed.

关于在不将其他任何内容硬编码到 exe 中的情况下修复此问题的任何提示?

Any tips on fixing this without hard-coding anything else into the exe?

推荐答案

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

Alien's string type is for pointers to strings only, that is why your example is not working. Try this:

-- 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 属性:

Now just allocate an LOFGONF structure as usual, but use the get_lfname and set_lfname functions to work with the lfFaceName attribute:

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 的下一个版本中直接支持它.

Tacking an array at the end is a common pattern for structures in C programming that I forgot. I am going to put direct support for it in the next version of Alien.

这篇关于Lua Alien - 调用特定的 API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆