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

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

问题描述

我目前运行的是成为一个问题,而与Lua和外星人模块玩弄使用的Win32 API和从这样的Lua脚本。到目前为止,我只与外国人这与使用API​​的使用某些结构如CreateFontIndirect单一的问题。

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 );

LOGFONT:

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。

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.

这是我得到的工作到一个点:

This is what I got working to a point:

 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'
 }

一个例子来调用它:

An example to call it:

 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语言编程,我忘结构的通用模式。我打算把它在外来的下一个版本的直接支持。

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的外国人 - 调用特定的API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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