以下の頻出パターンをカプセル化するマクロを定義したいと思います。コードはlispworksのFLI用です。
(fli:with-foreign-string ;; class name pointer
(cn-p ec bc :external-format (external-format)) "BUTTON"
(fli:with-foreign-string ;; window name pointer
(wn-p ec bc :external-format (external-format)) "Configuartion:server"
(let ((grpbx (createwindowex 0 cn-p wn-p
(logior ws_visible ws_child bs_groupbox)
0 0 300 420 hwnd 1 (GetModuleHandle-current 0) 0)))
(fli:with-foreign-string ;; class name pointer
(cn-p ec bc :external-format (external-format)) "EDIT"
(fli:with-foreign-string ;; window name pointer
(wn-p ec bc :external-format (external-format)) "192.168.200.200"
(createwindowex 0 cn-p wn-p
(logior ws_visible ws_child ws_border)
10 30 150 30 hwnd 1 (GetModuleHandle-current 0) 0)
)))))
作成したいマクロは次のようなものです: strsパラメータは文字列のリストです。たとえば、上記の("BUTTON" "Configuartion:server")では、 str-symsはcreatewindowexに供給される変換された文字列を蓄積します。私を混乱させたのは、使用する文字列(cn-p と wn-p)がボディの真ん中にあり、ボディを 2 つの部分 ( part-bdyと&body bdy) に分割する必要があったことです。
しかし、問題は、 LETブロックの最初の部分( createwindowexの前) であるpart-bdyに多くの括弧があり、その対応する部分が send 部分(&body bdy)にのみあることです。これは、part-bdyの括弧が開いておらず、評価時にエラーが発生することを意味します。それを解決するように私にアドバイスする賢いアイデアはありますか?
(defmacro with-foreign-string (strs str-syms part-bdy &body bdy)
(let ((g (gensym)))
(if (null strs)
(append part-bdy str-syms bdy)
`(fli:with-foreign-string
(,g ec bc :external-format (external-format)) ,(car strs)
(with-foreign-string ,(cdr strs) ,(cons g str-syms) ,part-bdy ,@bdy)))))