如何创建与C宏对应的Lisp FLI函数

use*_*328 3 lisp common-lisp ffi c-preprocessor lispworks

我想创建一个与C中的宏对应的lisp函数.例如,win32 API中有一个HIWORD,它被定义为头文件中的一个宏.

我尝试将其定义如下,但被告知HIWORD尚未解决.

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

我只是想知道如何为C函数创建C宏的包装器.

(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)
Run Code Online (Sandbox Code Playgroud)

Dir*_*irk 7

你不能直接这样做.C预处理器宏不会在编译过程中保留,即生成的目标文件中根本没有工件,这对应于C宏本身(尽管它的扩展可能是目标文件的一部分多次).由于没有工件,因此没有任何东西可以与FFI绑定.

但是,您可以提供包装函数

#define HIGHWORD(x)     /* whatever */

int 
highword_wrapper(int x)
{
    return HIGHWORD(x);
}
Run Code Online (Sandbox Code Playgroud)

这个可以和FFI一起使用.


Kaz*_*Kaz 6

无需跳入另一种语言.在Lisp中移位和屏蔽:

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

(defun loword (val) ;; ditto
  (logand val #xFFFF))
Run Code Online (Sandbox Code Playgroud)

另一种方法:使用ldb带有使用byte语法表示的范围的访问器:

(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.
Run Code Online (Sandbox Code Playgroud)