COMMON LISP JP > Archives > 2013/11/04

2013/11/04 01:32:19 UTC_
#
> Unknown CFFI type: :STRUCT."

このエラーは、CFFIのバージョンが古い場合に発生するようです。

https://github.com/tkych/quicksearch/issues/1
http://comments.gmane.org/gmane.lisp.quicklisp/469

おそらく、システムディレクトリ(/usr/share/common-lisp とか)にインストールされている古いバージョンのCFFIが、Quicklispでインストールされている新しいCFFIよりも優先的にロードされてしまっているものと思います。
システムにインストールされているCFFIを削除すれば(あるいはシステムのCFFIのバージョンを上げれば)、問題は起きなくなると思います。

そんなことをせずとも、Quicklispのライブラリを優先させる方法が何かあるとは思うのですが、まだ分かっていません。
たぶん ASDFの ~/.config/common-lisp/source-registry.conf あたりじゃないかと思うのだけれど、どう書いても ASDF/SOURCE-REGISTRY:INVALID-SOURCE-REGISTRY エラーになってしまって……http://common-lisp.net/project/asdf/asdf/Controlling-where-ASDF-searches-for-systems.html
2013/11/04 11:39:35 UTC_
#
解決法が分かりました。

#+quicklisp
(quicklisp:use-only-quicklisp-systems)
処理系の初期化ファイル(~/.sbclrc 等)に
を書き足して見てください。

ディストリビューションのパッケージ管理システムによりCFFI (0.10.6)がインストールされている状態で sbcl --load sdl-tutorial05.lisp を実行すると、kaiさんのと同じエラーが起きること、及び (quicklisp:use-only-quicklisp-systems) を初期化ファイルに書いておくと同エラーが生じないことを、確認しました。
2013/11/04 12:39:05 UTCkai
#
おかげさまで無事動きました。ありがとうございます。
2013/11/04 13:12:29 UTCkai
#
あと他のライブラリでもわからないところがあります。clをjavascriptにコンパイルするjsclというライブラリに関してです。自分はそれを使ってjavascriptのcanvasに線を引くコードを書くことにしました。
#
onload = function() {
  draw();
};
function draw() {
  /* canvas要素のノードオブジェクト */
  var canvas = document.getElementById('canvassample');
  /* canvas要素の存在チェックとCanvas未対応ブラウザの対処 */
  if ( ! canvas || ! canvas.getContext ) {
    return false;
  }
  /* 2Dコンテキスト */
  var ctx = canvas.getContext('2d');
  /* 四角を描く */
  ctx.beginPath();
  ctx.moveTo(20, 20);
  ctx.lineTo(120, 20);
  ctx.lineTo(120, 120);
  ctx.lineTo(20, 120);
  ctx.closePath();
  ctx.stroke();
}
2013/11/04 13:19:46 UTCkai
#
このコードをもとにjsclのreplで試し、canvas.getContext('2d');の部分まではいけました。ですが、その後で問題が発生しました。
2013/11/04 13:33:00 UTCkai
#
jsclでは(#j:canvassample:getContext "2d")というような感じで、2dコンテキストを取得できます。僕はもとにしたコードにならい(setf ctx (#j:canvassample:getContext "2d"))をし,てそのあとのコードを(ctx:beginpath)や(#j:ctx:beginPath)やさまざまな方法でc
#
送り間違えました
#
(訂正)jsclでは(#j:canvassample:getContext "2d")というような感じで、2dコンテキストを取得できます。僕はもとにしたコードにならい(setf ctx (#j:canvassample:getContext "2d"))をし,そのあとの描画の部分をctxをつかった(ctx:beginpath)や(#j:ctx:beginPath)などさまざまなことを試しました。しかし、ctxをつかってbeginPathなどの関数を使うことができませんでした。
2013/11/04 13:46:27 UTCkai
#
jsclにはチュートリアルがないようなのでgithubのissuesを見ると、(cl::oget ctx "biginPath")で#<FUNCTION>がでるようなのですが、関数自体は実行ができませんでした。さきほど書いたように(#j:canvassample:getContext "2d")とすると関数が実行できるのですが、(setf ctx (#j:canvassample:getContext "2d"))と置き換えなければならないときの関数の使い方が分かりません。どなた助けてください。
2013/11/04 17:43:44 UTC_
#
cl::oget の呼び出しをさらに括弧でくくると、取得した関数の呼び出しになるようです。
#
CL-USER> (defvar canvas (#j:document:createElement "canvas"))
CANVAS
CL-USER> (cl::oget canvas "getContext")        ;canvas.getContext;
#<FUNCTION>
CL-USER> ((cl::oget canvas "getContext") "2d") ;canvas.getContext("2d");
#<javascript object>
#
コンテキストオブジェクトのメソッドも同様にすれば呼び出せるはず。そう思ったのですが、バグっているらしく出来ませんでした(Firefoxで確認)。
#
CL-USER> (defvar context ((cl::oget canvas "getContext") "2d"))
CONTEXT
CL-USER> (cl::oget context "beginPath")
#<FUNCTION> ;関数の取得はできている
CL-USER> ((cl::oget context "beginPath")) ;でも呼び出すと…
ERROR: Variable `*' is unbound.
#
一度こうなると以降どんな式を評価しても "ERROR: Variable `*' is unbound." となってしまいます。