#:g1: VAX LISPのFFIを試してみる

Posted 2022-01-03 21:17:23 GMT

こちらのツイートを目にして、そういえばVAX LISPのFFIって試したことがなかったので、この機会に試してみることにしました。

試したのは、紹介されているbit誌のコードで、試した処理系はLiving Computersに設置されているVAX-7000/640上のVAX LISP 3.1です。

まず、Cのコードを作成、

#include <stdio.h>

be_good (times, string)
int times;
char string[];
{
int count;
for (count=0; count < times; count++)
    printf ("%s, I must not be so.\n", string);
printf("\n");
return(times);
}

$ cc be_good.c

$ link/shareable=[user.masso]be_good be_good,sys$input:/option #改行 universal=be_good #^Zで完了

VAX LISPを起動し下記を定義

(define-external-routine (be-good :image-name "be_good" :entry-point "be_good" :result integer)
  (times :lisp-type integer :mechanism :value)
  (person :lisp-type string :vax-type :asciz))

call-outで実行してみる

Lisp> (call-out be-good 10 "Daddy")
Error in SYSTEM::%SP-CALL-OUT:
%LIB-E-ACTIMAGE, error activating image SCSI$DIA0:[SYS0.SYSCOMMON.][SYSLIB]BE_GOOD.EXE;
-RMS-E-FNF, file not found

Control Stack Debugger Eval #10: (SYSTEM::%SP-CALL-OUT 10 "Daddy" 2 #:G556)

どうもBE_GOOD.EXEの場所を見付けてくれない様子……。
ファイルの絶対パス指定等を試してみましたが、解明すべき謎が多すぎるので諦めました。

下記のようなマニュアルの他の例は動くようなのでファイルの場所さえ適切に指定できれば動きそうではあります。

(define-external-routine (put-screen :image-name "scrshr"
                                     :entry-point "lib$put_screen"
                                     :result integer)
  (chars :lisp-type string)
  (line :lisp-type integer
        :vax-type :word)
  (col :lisp-type integer
       :vax-type :word)
  (flag :lisp-type integer
        :vax-type :word))

cffiで同じ例を試してみる

このままでは若干寂しいのでcffiで同じ例を試して比較してみることにしました。

#include <stdio.h>

int be_good (int times, char string[])
{
  for (int count = 0; count < times; count++)
    printf ("%s, I must not be so.\n", string);
  printf("\n");
  return(times);
}

lib-be-good.cとして用意し、

gcc -shared be_good.c -o lib-be-good.so

(ql:quickload "cffi")

(defpackage "2657427c-2fcb-5f17-abc2-5439545b51fa" (:use "CL" "CFFI"))

(in-package "2657427c-2fcb-5f17-abc2-5439545b51fa")

(define-foreign-library lib-be-good (T (:default "lib-be-good")))

(use-foreign-library lib-be-good)

と定義。
VAX LISPのcall-outに相当しそうな、foreign-funcallで呼び出してみると、

(with-foreign-string (person "Daddy")
  (foreign-funcall "be_good":int 10 :string person 
                   :int))

Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.
Daddy, I must not be so.

という風にできました。
with-foreign-stringは無しでも動きますが、一応メモリ周りの処理をしてくれるので利用しています。

まとめ

VMSでは、Common Language Environmentという言語間で共通の呼出規約が定められていたようで、色々な言語を簡単に混ぜて使えたようです。
マニュアルでもFortranのコードを呼び出す例が紹介されていたりしますが、共通の形式になるので呼び出す側からは元の言語はあまり意識しなくて良い様子です。


HTML generated by 3bmd in LispWorks 8.0.0

comments powered by Disqus