【问题标题】:Calling standard open dialog with LuaJIT gives access violation使用 LuaJIT 调用标准打开对话框会导致访问冲突
【发布时间】:2012-08-04 12:34:09
【问题描述】:

使用 LuaJIT 的 FFI 关注 MSDN's GetOpenFileName example。我已经尝试让这个工作两天了,不仅对话框没有打开,而且整个事情都崩溃了。

当使用 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]","\0")
  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\0*.*\0Text\0*.TXT\0"
  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 winapi lua ffi luajit


    【解决方案1】:

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

    【讨论】:

    • 哦,太尴尬了,谢谢你,工作完美无缺。迷失在翻译中:)
    猜你喜欢
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    相关资源
    最近更新 更多