3

I want to create a lisp function which corresponds to a macro in C. e.g., there is one HIWORD in win32 API, which is defined as a macro in the header file.

I tried to define it as below but was told that HIWORD is unresolved.

CL-USER 4 > (hiword #xFFFFFFFF)
Error: Foreign function HIWORD trying to call to unresolved external function "HIWORDW".

I just want to know how to create a wrapper for C macros like for C functions.

(fli:define-c-typedef DWORD (:unsigned :long))
(fli:define-c-typedef WORD (:unsigned :short))

(fli:define-foreign-function
        (HIWORD "HIWORD" :dbcs)
        ((dwVal dword))
        :result-type word :calling-convention :stdcall)
Cactus
  • 27,075
  • 9
  • 69
  • 149
user1461328
  • 742
  • 2
  • 6
  • 13

2 Answers2

7

You cannot do this directly. C preprocessor macros are not preserved in the compilation process, i.e., there is simply no artifact in the generated object files, which would correspond to the C macro itself (though its expansion may be part of the object file multiple times). And since there is no artifact, there is nothing to bind to with FFI.

You can, however, provide a wrapper function

#define HIGHWORD(x)     /* whatever */

int 
highword_wrapper(int x)
{
    return HIGHWORD(x);
}

and this one can be used with FFI.

Dirk
  • 30,623
  • 8
  • 82
  • 102
6

No need to jump into another language. Shifting and masking in Lisp:

(defun hiword (val)
  (logand (ash val -16) #xFFFF)

(defun loword (val) ;; ditto
  (logand val #xFFFF))

Another way: using the ldb accessor with ranges expressed using byte syntax:

(defun hiword (val)
  (ldb (byte 16 16) val)  ;; get 16-bit-wide "byte" starting at bit 16.

(defun loword (val)
  (ldb (byte 16 0) val)   ;; get 16-bit-wide "byte" at position 0.
Kaz
  • 55,781
  • 9
  • 100
  • 149