sdl2:load-bmp 当前工作目录问题,common-lisp

sdl2:load-bmp Problem with current working directory, common-lisp

在尝试完成 cl-sdl2-tutorial 时,由于当前工作目录错误,我无法加载位图。
我想使用相对路径名来正确解决问题。

一个最小的工作示例:
修改了上述教程中示例二的代码。

(defpackage #:sdl2-tutorial-2
  (:use :common-lisp)
  (:export :main))

(in-package :sdl2-tutorial-2)

(defparameter *screen-width* 640)
(defparameter *screen-height* 480)

(defmacro with-window-surface ((window surface) &body body)
  `(sdl2:with-init (:video)
     (sdl2:with-window (,window
                        :title "SDL2 Tutorial"
                        :w *screen-width*
                        :h *screen-height*
                        :flags '(:shown))
       (let ((,surface (sdl2:get-window-surface ,window)))
         ,@body))))

(defun main(&key (delay 2000))
  (format t " cwd: ~a, ~% dpd: ~a, ~& e-p: ~a, ~% pf: ~a, ~& load: ~a"
          (sb-posix:getcwd)
          *default-pathname-defaults*
          (uiop:file-exists-p "hello_world.bmp")
          (probe-file "hello_world.bmp")
          (sdl2:load-bmp "hello_world.bmp"))
  
  (with-window-surface (window screen-surface)
    (let ((image (sdl2:load-bmp "hello_world.bmp")))
      (break "1 here with ~a~%" image)
      (setf image (sdl2:load-bmp "hello_world.bmp"))
      (break "2 here with ~a~%" image)
      (break "3 error: ~a~%" (sdl2-ffi.functions:sdl-get-error))
      (sdl2:blit-surface image
                         nil
                         screen-surface
                         nil)
      (sdl2:update-window window)
      (sdl2:with-event-loop (:method :poll)
        (:quit () t)
        (:idle ()
               (sdl2:delay delay))))))

在编译上面的代码和 运行 (main) 之前,我更改了 REPL 中的工作目录,通过:

(sb-posix:chdir (truename "/test/cl-sdl2-tutorial/2/"))
(setf *default-pathname-defaults* (truename "/test/cl-sdl2-tutorial/2/"))

如预期的那样,上面的代码在 REPL 中 运行 (main) 时打印:

SDL2-TUTORIAL-2> (sdl2-tutorial-2:main)
  0: (SDL2-TUTORIAL-2:MAIN)
 cwd: /test/cl-sdl2-tutorial/2, 
 dpd: /test/cl-sdl2-tutorial/2/, 
 e-p: /test/cl-sdl2-tutorial/2/hello_world.bmp, 
 pf: /test/cl-sdl2-tutorial/2/hello_world.bmp, 
 load: #<SDL-SURFACE {#X7F5CBC018DD0}>

问题:
找不到位图,因此未加载。
(sdl2:load-bmp "hello_world.bmp") 的调用总是 return 零指针 (#<SDL-SURFACE {#X00000000}>) 和断点 3 状态:

3 error: Couldn't open /home/jue/hello_world.bmp

但是在断点 1 或 2 或 3 的中断期间评估 (sdl2:load-bmp "hello_world.bmp") 是成功的并且继续 (main) 显示图片。

问题:

备注 (我在 Linux 机器上使用 sbclEmacssly 的当前发布版本,如果这很重要的话。我只是 Common Lisp 的中等经验及其开发环境,但在 elisp 上更高级)

我怀疑但不知道问题出在 sdl2 库对线程的幻想,结果工作目录不是你想的那样。

根据我的经验,解决这个问题的方法是永远不要让实施事后猜测你喜欢那样。在任何情况下,如果有一些接口说“对文件做某事”,就给它一个绝对路径名,这样它就没有机会自己做任何事情。做一些类似的事情。

(defparameter *where-my-bitmaps-live* (merge-pathnames
                                       (pathname "lib/bitmaps/")
                                       (user-homedir-pathname)))

...

(defun load-a-bitmap (name)
  (load-bmp (merge-pathnames (pathname name) *where-my-bitmaps-live*)))

而且现在真的找不着借口了

(你想检查一下上面的pathname-mergery是否真的正确:好像是给我的,但是我每次看别处超过几分钟就忘记了pathname规则的细节)。