C语言 使用 LuaJIT 调用标准打开对话框会导致访问冲突



遵循MSDN的GetOpenFileName示例,使用LuaJIT的FFI。两天来,我一直在尝试让它工作,不仅对话框无法打开,而且会使整个事情崩溃。

当使用 OllyDdb 调试时,它会在 comdlg32.dll 中的某个地方抛出丑陋的访问冲突。

这是仅包含基本代码的概念证明。如果我指定结构大小为零,它会毫无问题地退出,GetLastError() 抛出 87 (ERROR_INVALID_PARAMETER)

所以我认为问题与结构或 FFI 有关。

如果有人能够在这里提供一些启示......谢谢。

ffi = require"ffi"
bit = require"bit"
collectgarbage("stop")
ffi.cdef[[
  static const int OFN_FILEMUSTEXIST             = 0x1000;
  static const int OFN_NOCHANGEDIR               = 8;
  static const int OFN_PATHMUSTEXIST             = 0x800;
  typedef bool BOOL;
  typedef char CHAR;
  typedef unsigned short WORD; 
  typedef unsigned long DWORD;
  typedef void *PVOID;
  typedef void *LPVOID;
  typedef void *LPOFNHOOKPROC;
  typedef unsigned long HANDLE;
  typedef HANDLE HWND;
  typedef HANDLE HINSTANCE;
  typedef const char *LPCSTR;
  typedef const char *LPCTSTR;
  typedef char *LPSTR;
  typedef char *LPTSTR;
  typedef unsigned long LPARAM;
  typedef struct {
    DWORD         lStructSize;
    HWND          hwndOwner;
    HINSTANCE     hInstance;
    LPCTSTR       lpstrFilter;
    LPTSTR        lpstrCustomFilter;
    DWORD         nMaxCustFilter;
    DWORD         nFilterIndex;
    LPTSTR        lpstrFile;
    DWORD         nMaxFile;
    LPTSTR        lpstrFileTitle;
    DWORD         nMaxFileTitle;
    LPCTSTR       lpstrInitialDir;
    LPCTSTR       lpstrTitle;
    DWORD         flags;
    WORD          nFileOffset;
    WORD          nFileExtension;
    LPCTSTR       lpstrDefExt;
    LPARAM        lCustData;
    LPOFNHOOKPROC lpfnHook;
    LPCTSTR       lpTemplateName;
    LPVOID        pvReserved;
    DWORD         dwReserved;
    DWORD         flagsEx;
  }OPENFILENAME;
  BOOL GetSaveFileNameA( OPENFILENAME lpofn );
  BOOL GetOpenFileNameA( OPENFILENAME lpofn );
]]
com=ffi.load("comdlg32")
ffi.cdef[[
  DWORD GetLastError(void);
]]
krnl=ffi.load("kernel32")
function OpenDialog()
  Ofn=ffi.new("OPENFILENAME")
  ffi.fill(Ofn,ffi.sizeof(Ofn)) --zero fill the structure
  local szFile        = ffi.new("char[260]","")
  local hwnd          = ffi.new("HWND",0)
  Ofn.lStructSize     = ffi.sizeof(Ofn)
  Ofn.hwndOwner       = hwnd
  Ofn.lpstrFile       = szFile
  Ofn.nMaxFile        = ffi.sizeof(szFile)
  Ofn.lpstrFilter     = "All*.*Text*.TXT"
  Ofn.nFilterIndex    = 1
  Ofn.lpstrFileTitle  = nil
  Ofn.nMaxFileTitle   = 0
  Ofn.lpstrInitialDir = nil
  Ofn.flags           = bit.bor(com.OFN_PATHMUSTEXIST, com.OFN_FILEMUSTEXIST, com.OFN_NOCHANGEDIR)
  print("displaying...")
  if com.GetOpenFileNameA(Ofn) then --luajit converts bool automatically
    print("file->",ffi.string(Ofn.lpstrFile, Ofn.nMaxFile))
  end
  print("lasterror->",krnl.GetLastError())
end
OpenDialog()

这些 C 函数采用指向结构的指针。正确的声明是:GetOpenFilenameA(OPENFILENAME *lpofn)等。

最新更新