如何在advice-add修饰的函数中获取原函数函数名?

我写了一组advice函数去监控函数的执行时间,其中有一个:around advice取执行函数的函数名,但是取打印出来的内容不合预期。 代码示例如下:

 (defun demo/msg-log (OLDFUN &rest args)
   (message "%s" OLDFUN)
   (apply OLDFUN args))

(advice-add 'switch-to-buffer :around 'demo/msg-log)

打印内容如下:

#[769 \301^C!^H?^A\302 =\203^P^@^H\203\235^@\303 \203,^@^H\204,^@^B\203$^@\304\305!\210\202\235^@\306^B^E"\210\202\235^@\307 \310=\203J^@^H\204J^@^B\203B^@\304\311!\210\202\235^@\306^B^E"\210\202\235^@^H\203a^@\312 \313^C^F^F"\210\312 ^A=\\
203`^@\310\262^B\210\211\203\235^@^A\314 \236\315\316^D"\211\317=\205w^@\320^D\321"\322\323^F^F"\210^B\203\233^@^A\310=\204\213^@\211\203\233^@\324\312 ^DA@\310#\210\325\323\326^E8"\210\266^C^C\204\246^@\327\312 !\210^Aq\207 [switch-to-buf\
fer-obey-display-actions window-normalize-buffer-to-switch-to window-buffer window-minibuffer-p user-error Cannot switch buffers in minibuffer window pop-to-buffer window-dedicated-p t Cannot switch buffers in a dedicated window selected-w\
indow pop-to-buffer-same-window window-prev-buffers buffer-local-value switch-to-buffer-preserve-window-point already-displayed get-buffer-window 0 set-window-buffer nil set-window-start set-window-point 2 select-window] 12 (window.elc . 2\
68751) (byte-code ^H?\205H^@\302 \203^N^@\303\202H^@\304 \305=\204^Y^@\306\202H^@   \307\267\202B^@\310\311!\202H^@\312\313\314\315 "!\2038^@\316\303\211"\210\306\202H^@\310\311!\202H^@\303\202H^@\316\303\211"\210\306\317\320!\303^BE\207 [\
switch-to-buffer-obey-display-actions switch-to-buffer-in-dedicated-window window-minibuffer-p nil window-dedicated-p t force-same-window #s(hash-table size 3 test eq rehash-size 1.5 rehash-threshold 0.8125 purecopy t data (nil 31 prompt 3\
7 pop 62)) user-error Cannot switch buffers in a dedicated window y-or-n-p format Window is dedicated to %s; undedicate it? window-buffer set-window-dedicated-p read-buffer-to-switch Switch to buffer: ]

我希望它能打印出swith-to-buffer,请问应该怎么办?

另外,如果有其它的可以直接获取函数执行时间的方法,也请指教下,谢谢!

建议把示例代码再提炼一下,去掉与问题无关的代码,只保留能说明问题的最小代码。

  1. backtrace-frame 可以获得调用信息,但是非常不靠谱,套一层 (progn ...) 都会导致结果改变:
;; emacs -Q --batch --eval
(progn
  (defun foo ()
    nil)

  (defun bar ()
    nil)

  (defun ad-body ()
    (let ((caller (backtrace-frame 4)))
      (message "==> caller: %s" caller)))

  (dolist (symbol '(foo bar))
    (advice-add symbol :before 'ad-body))

  (foo)
  (bar))
;; ==> caller: (t foo)
;; ==> caller: (t bar)
  1. 动态生成 advice, 但是不好调试
;; emacs -Q --batch --eval
(progn
  (defun foo ()
    nil)

  (defun bar ()
    nil)

  (dolist (symbol '(foo bar))
    (advice-add symbol :before `(lambda ()
                                  (message "==> caller: %s" ',symbol))))

  (foo)
  (bar))
;; ==> caller: foo
;; ==> caller: bar
  1. 通过变量传递调用者信息
;; emacs -Q --batch --eval
(progn
  (defun foo ()
    nil)

  (defun bar ()
    nil)

  (defvar caller nil)
  (defun ad-body ()
    (message "==> caller: %s" caller))

  (dolist (symbol '(foo bar))
    (advice-add symbol :before `(lambda ()
                                  (let ((caller ',symbol))
                                    (ad-body)))))

  (foo)
  (bar))
;; ==> caller: foo
;; ==> caller: bar

感谢,第二个例子非常有用,我之前也尝试过,但是没能成功,应该是还没有搞明白`',这三个符号的用法。