Cの定数値や型のサイズを取得するための関数
sb-alienパッケージとかを使ってネイティブライブラリを使用していると、ちょくちょくCの定数の値や型の定義(型のサイズ)を知りたくなることがある。
毎回ヘッダファイルを調べるのも面倒なので、lisp上から取得出来るように関数を用意してみた。
(defun c-inspect (&key include type value) (flet ((gen-source () (with-output-to-string (out) (format out "~&#include <iostream>~%") (dolist (inc include) (format out "~&#include <~a>~%" inc)) (format out "~%int main() {~%") (dolist (ty type) (format out " std::cout << \"sizeof(~a) = \" << sizeof(~a) << std::endl;~%" ty ty)) (dolist (val value) (format out " std::cout << \"~a = \" << ~a << std::endl;~%" val val)) (format out "}~%")))) ;; 定数や型の情報を出力するためのC++ソースを生成 (with-input-from-string (in (gen-source)) ;; 生成したソースをコンパイル (let ((ret (sb-ext:run-program "g++" `("-x" "c++" "-" "-o" "/tmp/c.inspect.tmp") :search t :input in :output t))) ;; コンパイルに成功しているなら、コマンドを実行 (when (zerop (sb-ext:process-exit-code ret)) (sb-ext:run-program "/tmp/c.inspect.tmp" '() :output t))))) (values))
使用例。
> (c-inspect :type '("int" "unsigned long" "void *") :value '("NULL")) sizeof(int) = 4 sizeof(unsigned long) = 8 sizeof(void *) = 8 NULL = 0 > (c-inspect :include '("sys/socket.h") :value '("PF_UNIX" "SO_ACCEPTCONN" "SO_ERROR")) PF_UNIX = 1 SO_ACCEPTCONN = 30 SO_ERROR = 4 ;; エラー > (c-inspect :type '("undefined_type")) <stdin>: In function ‘int main()’: <stdin>:4: error: ‘undefined_type’ was not declared in this scope