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)
显示图片。
问题:
- 为什么
sdl2:load-bmp
使用“错误”的工作目录,为什么在断点期间使用“正确”的工作目录?
- 如何使
sdl2:load-bmp
在使用相对路径时使用所需的工作目录(而不是“/home/jue/”)?
备注
(我在 Linux 机器上使用 sbcl
、Emacs
、sly
的当前发布版本,如果这很重要的话。我只是 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规则的细节)。
在尝试完成 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)
显示图片。
问题:
- 为什么
sdl2:load-bmp
使用“错误”的工作目录,为什么在断点期间使用“正确”的工作目录? - 如何使
sdl2:load-bmp
在使用相对路径时使用所需的工作目录(而不是“/home/jue/”)?
备注
(我在 Linux 机器上使用 sbcl
、Emacs
、sly
的当前发布版本,如果这很重要的话。我只是 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规则的细节)。