「hmLJ」から「ネイティブdll」のWin32 APIを利用する。

  • 概要

    hmLJでwin32を利用したプログラムを呼び出す王道は、
    あくまでもlua/luajit用のモジュールを作るといったものです。

    しかし、「比較的簡易なwin32apiをポツポツ数個利用するだけなのに…」といった場合は、
    hmLJ(LuaJit)に備わっているFFI libraryを利用するのが便利かもしれません。

  • FFI FFI Library

    以下のページにFFIの使い方のリファレンスが掲載されています。

  • FFI Libraryの使用例

    luajitのFFIの使用例はネット上を検索すれば数多く発見できるでしょう。
    ここでは、代表的な例を例示します。

    #L = loaddll( hidemarudir + "\\hmLJ.dll");
    
    #_ = dllfunc(#L, "SetStrVar", "szOrgPath", "C:\\Program Files");
    
    // win32APIの「PathQuoteSpaces」を利用してみる
    // 「PathQuoteSpaces」は文字列に空白があれば二重引用符で囲む関数。
    #_ = dllfunc(#L, "DoString", ""+
    "ffi.cdef[[\n" +
    "typedef char *         LPTSTR;  \n" +
    "int PathQuoteSpacesA(LPTSTR lpFilename);\n" +
    "]]\n" +
    "shlwapi = ffi.load('shlwapi')\n" +
    "szPathBuf = ffi.new('char[?]', 256, szOrgPath)\n" +
    "ret = shlwapi.PathQuoteSpacesA( szPathBuf )\n" +
    "szPathBuf = ffi.string(szPathBuf)"
    );
    
    //
    $strQuotePath = dllfuncstr(#L, "GetStrVar", "szPathBuf");
    
    message($strQuotePath);
    
    // 「GetModuleFileNameA」を利用する。
    // 「GetModuleFileNameA」引数で指定したプロセスアドレス空間に展開されているプログラム(exeやdll等)のフルパス名を取得する関数
    #_ = dllfunc(#L, "DoString", ""+
    "ffi.cdef[[\n" +
    "typedef void *         HMODULE; \n" +
    "typedef char *         LPTSTR;  \n" +
    "typedef unsigned short DWORD;   \n" +
    "DWORD GetModuleFileNameA(HMODULE hModule, LPTSTR lpFilename, DWORD nSize);\n" +
    "]]\n" +
    "kernel32 = ffi.load('kernel32')\n" +
    "szPathBuf = ffi.new('char[?]', 256)\n" +
    "ret = kernel32.GetModuleFileNameA( nil, szPathBuf, 256 )\n" +
    "szPathBuf = ffi.string(szPathBuf)"
    );
    
    $strBufFileName = dllfuncstr(#L, "GetStrVar", "szPathBuf");
    
    message($strBufFileName);
    
    // wsprintfAを利用する。
    // 但し、「sprintfタイプの可変引数以外の目的」でcdeclを利用する機会は普通ないため、
    // このような無意味なことはやめて、lua層のstring.formatを使うのが良い
    #_ = dllfunc(#L, "DoString", ""+
    "ffi.cdef[[\n" +
    "int wsprintfA(char *buffer, const char *format, ...);\n" +
    "]]\n" +
    "user32 = ffi.load('user32')\n" +
    "szBuf = ffi.new('char[?]', 256)\n" +
    "ret = user32.wsprintfA( szBuf, '表示%sは%sです。', 'OK', '123' )\n" +
    "szBuf = ffi.string(szBuf)"
    );
    
    $strBufSprintf = dllfuncstr(#L, "GetStrVar", "szBuf");
    
    message($strBufSprintf);
    
    freedll(#L)