Lua Alien - Specialized API

Currently, I am facing a problem when working with Lua and a foreign module for using the Win32 API and such Lua scripts. So far, I have had only one alien problem that uses APIs that use certain structures like CreateFontIndirect.

For example:

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;

The problem is the face name of the font. I cannot force Lua to store the string inside the structure itself; it always pushes a pointer to the structure. Thus, I cannot understand to use this API exclusively from Lua.

Here is what I got from work:

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

Example for calling:

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

, script, , api , , . , , .

- - exe?

+3
2

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

- , . Alien.

+3

mascarenhas, . set_lfname, + i-1 lfPitchAndFamily , -1, .:)

-1

Source: https://habr.com/ru/post/1721466/


All Articles