1

I want to define a macro which encapsulates the frequent pattern below. The code is for FLI of lispworks.

(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) ))))) 

The macro I want to create is something like below: THe strs parameter is a list of strings, e.g. ("BUTTON" "Configuartion:server") above, str-syms accumulates the converted strings which will be fed to createwindowex. What confused me was that the strings to be used (cn-p and wn-p) are in the middle of the body, and I had to split the body into 2 parts: part-bdy and &body bdy.

But the problem is part-bdy, which is first part of LET block (before createwindowex), has many parentheses, whose counter parts are only in the send part (&body bdy). Which means the parentheses in part-bdy are not open and cause error when evaluated. Do you have any clever idea to advise me to solve it?

(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))))) 
2
  • 3
    A macro manipulates code, not parentheses. Could you add some detail, e.g. give a small, but complete example? Thanks. Commented Dec 18, 2016 at 8:18
  • 1
    You seem to be trying to insert your generated symbols in the middle of the body. You should instead let the user provide the symbols with a LET-like construct (with-foreign-strings ((class-name "BUTTON") (window-name "...")) ... (createwindowx 0 class-name window-name ...)) Commented Dec 18, 2016 at 8:40

1 Answer 1

2

Just want to share that I changed the macro as below:

(defmacro with-foreign-str (strs str-syms bdy) (if (null strs) bdy `(let ((,(car str-syms) (gensym))) (fli:with-foreign-string (,(car str-syms) ec bc :external-format (external-format)) ,(car strs) (with-foreign-str ,(cdr strs) ,(cdr str-syms) ,bdy))))) 

then the code code above without using the macro can be rewritten like this:

 (WITH-FOREIGN-STR ("BUTTON" "Configuartion: server") (cn-p wn-p) (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))) (WITH-FOREIGN-STR ("EDIT" "192.168.200.95") (cn-p3 wn-p3) (createwindowex 0 cn-p3 wn-p3 (logior ws_visible ws_child ws_border) 10 30 150 30 hwnd 1 (GetModuleHandle-current 0) 0)))) 

This is still not so clean but anyway I can manage to simplify the code using macro. There were not so many responses only because I think due to the FLI and win32 API in the code.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.