2009-10-30 4 views
3

저는 루아와 함께 Win32 API를 사용하기 위해 루아와 외계인 모듈을 다루는 동안 현재 문제를 겪었습니다. 지금까지 CreateFontIndirect와 같은 특정 구조를 사용하는 API를 사용하는 외계인과 관련된 문제는 하나만있었습니다. 예를 들어루아 에일리언 - 특정 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; 

문제는 폰트 페이스 명에 놓여있다. 루아가 구조체 내부에 문자열을 유지하도록 할 수는 없지만 항상 구조체에 포인터를 푸싱합니다. 그래서 루아에서이 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 구조를 할당하지만, lfFaceName 속성과 함께 작동하도록 get_lfname 및 set_lfname 기능을 사용 : 일반적인 패턴이다

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에 감사드립니다.이 솔루션이 효과가있었습니다. offset + i-1이 정렬되지 않고 구조체의 lfPitchAndFamily 바이트를 덮어 쓰고 -1을 제거 했으므로 set_lfname 함수를 조정해야했습니다. :)

+1

mascarenhas의 답변 아래 내용을 복사 한 다음이 대답을 삭제하고 대답을 수락하십시오 (왼쪽의 체크 표시를 클릭하십시오). –