`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2009-11-07

Shibuya.lisp テクニカルトーク#4 LT「弾幕記述言語BulletSMLのご紹介」

f:id:mokehehe:20091107234227p:image:right

Shibuya.lisp テクニカルトーク#4のLightning Talksで、「弾幕記述言語BulletSMLのご紹介」という題でお話させていただきました。スライドの内容を張っておきます。中途半端ですが、ソースはgithubに上げてあります。会の感想はまた後ほど。


弾幕記述言語

BulletSML

の ご紹介

mokehehe

----

自己紹介

----

id:mokehehe

http://cadr.g.hatena.ne.jp/mokehehe/

----

弾幕記述言語?

----

2Dシューティングゲームの

敵の弾の出現パターンや動作

を記述する言語

----

BulletML / ABA games

http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/

----

言語形式

----

XML

----

CODE:

"http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/bulletml.dtd">

<bulletml xmlns="http://www.asahi-net.or.jp/~cs8k-cyu/bulletml">

<action label="top">

<repeat>

<times>100</times>

<action>

<fire>

<direction type="sequence">23</direction>

<bullet/>

</fire>

<wait>1</wait>

</action>

</repeat>

</action>

</bulletml>

----

CODE:

action:

  動作の定義

repeat:

  指定した回数だけactionを繰り返す

fire:

  弾を発射

wait:

  指定時間だけ待つ

などなど...

----

解釈と

実行

----

Java

アプレット

----

XMLをパース

木の形式で保持

トラバースで実行

----

C++用ライブラリ

libbulletml / shinh

http://shinh.skr.jp/libbulletml/

----

Lisp

----

XML?

----

S式!

----

BulletSML

BulletMLのS式版

----

CODE:

(bulletml

(action :label top

(repeat

(times 100)

(action

(fire

(direction :type sequence

23)

(bullet))

(wait 1)))))

アトリビュートはPLISTで表現

----

解釈と

実行

----

マクロ

プログラムに

直接変換

----

CODE:

(bulletml

(action :label top

...))

   ↓

----

CODE:

(letrec ((%action-top

(lambda (self . $args)

...)))

%action-top)

・弾幕挙動の関数を返す

----

CODE:

(repeat

(times 3)

(action ...))

   ↓

----

CODE:

(dotimes (i 3)

(action ...))

----

CODE:

(action

...)

   ↓

----

CODE:

(begin

...)

----

CODE:

(wait 1)

  ↓

----

CODE:

(yield 1)

・継続を使用

----

動作

デモ

----

Gauche

+

SDL

----

弾幕データは

白い弾幕くん / shinh

のものを使用

http://shinh.skr.jp/sdmkun/

----

利点

----

DSL

普通の式も

使える

----

ただし、

あまり自由にやりすぎると

BulletMLとの

互換性がなくなるという罠

----

難点

----

継続/弾

は無謀

----

http://github.com/mokehehe/bulletsml

----

enjoy

danmaku

life!

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20091107

2009-10-29

Shibuya.lisp TT#4 ライトニングトークの発表内容決定!

no title

ま、タイトルだけで全てわかってしまう、出落ちということでみなさん生暖かい目でよろしくお願いします。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20091029

2009-10-09

Land of Lisp

"Land of Lisp"ってどうなんでしょうかね

ゲームを題材に、ってのは惹かれる

【入門】Common Lisp その6【質問よろず】

Land of Lisp
Land of Lisp
posted at 09.10.09
Conrad Barski
No Starch Press
売り上げランキング: 27002

  • こんな本が出るとは知らなかった…おもしろそうだな!
  • Common Lisp本#1 g000001さんのリストマニアが出てきたw ペロ…これは純度が高くて致死量を超えている…

g000001g0000012009/10/10 17:48Common Lisp本その2もあるんでよかったら見てくださいw
http://www.amazon.co.jp/gp/richpub/listmania/fullview/R1R0QJ8UWIY6

mokehehemokehehe2009/10/11 07:24#2のほうは今では手に入れにくい本が多そうですね

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20091009

2009-10-01

Arcでゴルフ

Route 477(2009-09-29)

> Arc

調査ありがとうございます。今度入れときます。

2009-09-29

Arcがゴルフ場に入る!ということで先に遊んでおく。自分の腕が不足してるのか案外短くならず、軒並みScheme(Gauche)に負けてるのが残念。つかSchemeでどうやってるんだろう…。

echo:23

(whilet c(readc)(pr c))

google:32

(pr'g(string(n-of(read)'o))'gle)

fizzbuzz:79

(= % multiple)(for i 1 100(prn(if(% i 15)'FizzBuzz(% i 3)'Fizz(% i 5)'Buzz i)))

Fibonacci Numbers:59

((afn(a b i)(when(< i 46)(self b(+(prn a)b)(+ i 1))))1 1 0)

ポートから1行読み込むreadlineの仕様が酷くて行頭に#\newlineがきても空行にしてくれないので、行単位になんかするもの、reverse linesをやろうとしてガッカリした。

Arcはウェブサーバに必要な機能に特化してそうなんで、いいとこだけとってゴルフという観点でLispを再設計したら面白いかもしれない。

mokehehemokehehe2009/10/06 16:17Anarchy-golfでArc始まった。
pr!g(repeat(read)pr!o)pr!gle

mokehehemokehehe2009/10/07 10:10((rfn f(a b)(if(< b 3e9)(f b(+(prn a)b))))1 1)

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20091001

2009-09-13

g000001さんを褒め称える

Google グループ

Google グループ

上のスレとかを見ると、id:g000001さんのすごさを感じずにはいられない。段取り力、アイデア出し、行動力、みんなへの意見の求め方・まとめ方など、全てにおいて抜きん出ている。

それもLispはいわば趣味の、1円にもならないことに関してこれだけ精力的に行動するモチベーションはどこから沸いてきているのかと、感嘆する。こういう人がコミュニティを作り支えているのだなぁと頼もしく思う。

g000001g0000012009/09/13 23:29いえいえ、多分、自分は割と迷走しているというか、声ばかり大きくて周りの方に迷惑をお掛けしてるんじゃないかなあと思っていますw
趣味で1円にもならないというのは、今のところ短所でも長所でもあって、完全にボランティアベースなので協力して貰いやすくなっているというのもありますねー。
個人的なモチベーションとしては、暇だからというのが最大の理由ですねw

mokehehemokehehe2009/09/15 08:42本当に素晴らしいと思います!期待してます!

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090913

2009-09-05

「コンピュータ将棋プログラムをLISPで書く」はミスリーディング

コンピュータ将棋プログラムをLISPで書く - やねうらお−ノーゲーム・ノーライフ

Yaneu Labs --- コンピュータ将棋プログラムをLISPで書く

Lisp愛好家狂喜!と思ったらタイトルで完全に釣り。「Lispで将棋の思考ルーチンを書く」という話じゃなくて「スクリプトでソース生成」という話じゃんか。ソースを生成するための言語としてLispを選ぶ理由も、自前で実装する理由もよくわからなかった。文字列処理に強い言語は他にもたくさんあるし、2日で実装した処理系よりよっぽど信頼度高いよ。

S式の評価はeval連発方式か…。そんなんでLispはメタプログラミングを多用するから遅いとか言ってちゃだめだよ!

「//%」で始まる行はLispソース、そうじゃない行は文字列扱い、という仕様かな?

Windowsのシェルが弱いのが全て悪いんや…だから既存のツールを組み合わせて使うという考えにならないんや…

  • はてブ みんなだまされすぎですよ!
    • インラインLispとかDSLとかいう話じゃ全然ないですよ!
    • Lispを組み込んで使うという話でもない
    • コンパイラという話でもなくて、単なる文字列置換ですよ!

yaneuraoyaneurao2009/09/05 13:51> 2日で実装した処理系よりよっぽど信頼度高いよ。

信頼度の問題ではないです。自分にとって使いやすいかどうかが大切です。トータルでの生産性は信頼度のみで決まるものではないからです。

> S式の評価はeval連発方式か…。そんなんでLispはメタプログラミングを多用するから遅いとか言ってちゃだめだよ!

これは、速度が要求されないところで用いるものだから、簡易実装としてそうしているだけです。

> コンパイラという話でもなくて、単なる文字列置換ですよ!

これで言語としてfixされているわけではないので(自分で作っているのだからどんどん手を入れることは出来る)、単なる文字置換以上のものだと思いますし、もう少し手を入れればDSLっぽいことだって出来ます。

だから、はてブでの評価は、別にみんな騙されているわけでも過大評価でもないと思いますよ。

mokehehemokehehe2009/09/06 00:16いやー大多数は「やねさんがLispですごいことをしてる」と勘違いしてると思いますよ。

> 最強クラスのコンピュータ将棋ソフトであるBonanzaとGPS将棋に関してはソースが公開されている。そのどちらも高速化には数々のテクニックが使われている。
> それなのに、LISPなんかに本当にトッププログラムと互角にやり合えるだけのポテンシャルがあるのか?

こう書いてあれば誰でもLispで思考ルーチンを作ってるのかと思いますよね。今回の話ははっきりいって将棋とは関係ないし、Lispも選択肢の1つでしかないですよね。

DSLというよりかは、テンプレートエンジンだと思いました。

yaneuraoyaneurao2009/09/06 01:14> こう書いてあれば誰でもLispで思考ルーチンを作ってるのかと思いますよね。

最後まで読めば小学生だってそれは違うことぐらいわかるでしょう。いくらなんでも「大多数」が最後まで読んでいないと言うのには無理があるのでは。

> 今回の話ははっきりいって将棋とは関係ないし

コンピュータ将棋は、高速化が命であり、そのためにコードを極度にunrollしなければならないので、そのためにコード生成を補助してくれるスクリプト or DSLが必要でそのスクリプトとしてLISPが最適だというのが私の主張なので、「コンピュータ将棋」と「LISP」とは大いに関係があります。

> Lispも選択肢の1つでしかないですよね。

parserが書きやすくて、かつ、関数がfirst class objectであり、かつ、数時間で実装できる言語を私はLISP以外に思いつかないので、私にとってはLISPが唯一無二の選択肢で、「選択肢のひとつ」ではないです。

この条件を満たすメジャーな(誰でも名前を聞いて内容を想像できるような)言語が他にあるなら、是非教えてもらいたいです。

> DSLというよりかは、テンプレートエンジンだと思いました。

それは使い方次第でしょう…。実際、コンピュータ将棋プログラムのコードを生成するのにLISP側で手に負えないことは、C#側で専用の関数をいくつも書いてます。ですので、私は単なる文字置換ソフトのつもりも、テンプレートエンジンのつもりもありません。

komagatakomagata2009/09/07 02:54僕もマクロを作った将棋向けDSLかと思ってたので、「文字列をevalするなら何でも良いじゃん」と思ってしまいました。wktkした分余計に。

mokehehemokehehe2009/09/07 07:06ご自分で
> yaneurao 2009/09/06 19:00
> ええ、ええ。しかしこれがCMならJAROに通報されますかね…。
と書いてるじゃないですか。

yaneuraoyaneurao2009/09/07 09:09↑*2
> 「文字列をevalするなら何でも良いじゃん」

意味がわからない。「ソースコード中のコメント行をevalする」話なのか、「evalできる言語ならなんでもいい」という話なのかどちら?また、なぜそれなら「何でも良い」と言えるの?

↑*1
記事のタイトルが釣りっぽいからと言って、みんなが本文の内容が理解できなくなって、中身が理解できずにはてブするわけではない。

あなたの主張は、みんなが内容を理解せずに騙されてはてブしているということだけど、それはタイトルが釣りっぽいこととは何ら関係がない。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090905

2009-08-15

g000001g0000012009/08/15 23:48ちなみに今のところCLの案件は0ですwww

mokehehemokehehe2009/08/16 23:07お客さん的にはなんの言語を使おうが構わないでしょうから、開発側がOKならいけちゃいますかね?

g000001g0000012009/08/17 00:25一番問題に対して楽に書ける言語であれば、なんでも構わないというスタンスです。しかし、自分は根性がないのでRoRの日々を送っておりますw

mokehehemokehehe2009/08/20 06:15g000001さんがRoRの方が楽ということは、RoRはよっぽど良くできてるんですね。私はレールに乗り損ねてます(^^;;

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090815

2009-08-09

GaucheでXML読み込み

例えば、BulletMLのxml

(define xml
"<?xml version=\"1.0\" ?>
<!DOCTYPE bulletml SYSTEM \"http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/bulletml.dtd\">

<bulletml xmlns=\"http://www.asahi-net.or.jp/~cs8k-cyu/bulletml\">

<action label=\"top\">
<repeat>
<times>100</times>
<action>
 <fire>
  <direction type=\"sequence\">23</direction>
  <bullet/>
 </fire>
 <wait>1</wait>
</action>
</repeat>
</action>

</bulletml>
")

を読み込むのにssax:xml->sxmlを使うと

>(use sxml.ssax)
#<undef>
> (ssax:xml->sxml (open-input-string xml) '())
(*TOP*
 (*PI* xml "version=\"1.0\" ")
 (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:bulletml
  (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:action (|@| (label "top"))
   (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:repeat
    (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:times "100")
    (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:action
     (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:fire
      (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:direction (|@| (type "sequence"))
       "23")
      (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:bullet))
     (http://www.asahi-net.or.jp/~cs8k-cyu/bulletml:wait "1"))))))

xmlnsがブリブリ付いてしまっていやだ。URI-STRINGで置き換えようにも正規表現が使えなくて文字列しか受け付けないのであらかじめ名前空間がわかってないと変換できない。そこでssax:make-parserで作ったパーサ:

(define (parse-xml xml-string)
  (car (xmlparser (open-input-string xml-string) '())))

(define xmlparser
  (ssax:make-parser
   NEW-LEVEL-SEED (lambda args '())
   FINISH-ELEMENT (lambda (elem-gi attributes namespaces expected-content seed)
                    `(,@expected-content (,(if (pair? elem-gi) (cdr elem-gi) elem-gi) ,@(attrlist->keylist attributes) ,@seed)))
   CHAR-DATA-HANDLER (lambda (text b c)
                       (let1 s (strip text)
                         (if (string=? s "")
                             (if (null? c)
                                 '()
                               c)
                           (if (null? c)
                               (list (str->value s))
                             (error "illegal")))))))

(define (attrlist->keylist attrlist)
  (apply append (map (lambda (e) (list (make-keyword (car e))
                                       (str->value (cdr e))))
                     attrlist)))

(define (str->value str)
  (cond ((#/^\d+(\.\d+)?$/ str) => (lambda (_) (read-from-string str)))
        ((#/^[\w_]+$/ str) => (lambda (_) (string->symbol str)))
        (else str)))

(define (strip str)
  (cond ((#/^\s*(.*?\S+)\s*$/ str) => (lambda (m) (m 1)))
        (else "")))

を使うと:

> (parse-xml xml)
(bulletml
 (action :label top
   (repeat
    (times 100)
    (action
     (fire
      (direction :type sequence
        23)
      (bullet))
     (wait 1)))))

すっきりして満足。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090809

2009-07-14

各言語のエラー情報

Gaucheはエラーが出たときに、スタックトレースは出力されるが肝心なエラーの発生したソース位置がわからないのが辛い。

RubyLua がシンプルかつ十分な情報で好みかな。Squirrelはローカル変数まで表示されてイイ!

Lispの中ではYpsilonのエラーメッセージが一番わかりやすい。

Gauche
gosh> (fib "hello")
*** ERROR: real number required: "hello"
Stack Trace:
_______________________________________
Ypsilon
> (fib "hello")

error in |comparison(< > <= >=)|: expected number, but got "hello", as argument 1

irritants:
  ("hello" 2)

backtrace:
  0  (< n 2)
  ..."d:/home/repos/misc/lisp/errmsg/fib.scm" line 2
  1  (+ (fib (- n 1)) (fib (- n 2)))
  ..."d:/home/repos/misc/lisp/errmsg/fib.scm" line 4
  2  (fib "hello")
  ..."/dev/stdin" line 1
Mosh
mosh>(fib "hello")

Unhandled exception:

 Condition components:
 1. &assertion
 2. &who             who: "<"
 3. &message         message: "number required required, but got (hello 2)"
 4. &irritants       irritants: ()
SBCL
* (fib "hello")

debugger invoked on a SIMPLE-TYPE-ERROR: Argument X is not a REAL: "hello"

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-KERNEL:TWO-ARG-< "hello" 2)
0] (backtrace)

0: (SB-KERNEL:TWO-ARG-< "hello" 2)
1: ("no debug information for frame")
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (FIB "hello") #<NULL-LEXENV>)
3: (INTERACTIVE-EVAL (FIB "hello"))[:EXTERNAL]
4: (SB-IMPL::REPL-FUN NIL)
5: ((LAMBDA ()))
6: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX #<CLOSURE (LAMBDA #) {23B5A735}>)
7: (SB-IMPL::TOPLEVEL-REPL NIL)
8: (SB-IMPL::TOPLEVEL-INIT)
9: ((LABELS SB-IMPL::RESTART-LISP))
10: ("foreign function: #x4120C4")
11: ("foreign function: #x40AF88")
Ruby
irb(main):002:0> fib "hello"
ArgumentError: comparison of String with 2 failed
        from ./fib.rb:2:in `<'
        from ./fib.rb:2:in `fib'
        from (irb):2
        from :0
Python
>>> fib.fib("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "fib.py", line 5, in fib
    return fib(n-1) + fib(n-2);
TypeError: unsupported operand type(s) for -: 'str' and 'int'

「"hello" < 2」はOK (False)で「"hello" - 1」がだめとか。わけわからん。

Lua
> fib("hello")
fib.lua:2: attempt to compare string with number
stack traceback:
        fib.lua:2: in function 'fib'
        stdin:1: in main chunk
        [C]: ?
Squirrel
sq>fib("hello")

AN ERROR HAS OCCURED [comparsion between 'hello' and '2']

CALLSTACK
*FUNCTION [fib()] fib.nut line [2]
*FUNCTION [main()] interactive console line [1]

LOCALS
[n] "hello"
[this] TABLE
[vargv] ARRAY
[this] TABLE
Crowbar
$ ./crowbar.exe fib.crb
  2:2項演算子>のオペランドの型が不正です。
Xtal
$ bin/xtal.exe fib.xtal
lib::builtin::UnsupportedError: lib::builtin::String::op_lt#<lib::builtin::Int>は定義されていません。
        fib.xtal:2: in filelocal::fib
        fib.xtal:9: in (instance of AnonymousClass) fib.xtal(1)

ちょw

Gaucheでのエラーの捕捉

CからGaucheの関数を呼び出すときに

	ScmEvalPacket epak;
	if (Scm_Apply(proc, args, &epak) >= 0) {
		...

としていたが、Scheme内でエラーが発生したときに例外オブジェクトは ScmEvalPacket::exception で取れるが、どこでエラーが起きたかとかの情報が出ないので困る。

404 Error - FC2ブログを見て、Gauchereplをまねてみたがうまくいかず…。

C側ではほとんど何もしてなくて、エラーをキャッチできてもどうやって復帰させるかの方法は知らないのでScheme側でキャッチしちゃっていいんじゃないの?と考えてguardなどを使えばいいんじゃないかと思ったけど、これも例外が取れるだけでどこで発生したかがわからない。

すったもんだしてたところ、Scm_Apply()の代わりにScm_ApplyRec()を使えばgoshで出るエラーメッセージが出力されスタックトレースも出力されることがわかった。ただこれだと、例外が投げられてめぐりめぐってvm.cのuser_eval_inner()内の

            ...
            else if (vm->cstack->prev == NULL) {
                /* This loop is the outermost C stack, and nobody will
                   capture the error.  Usually this means we're running
                   scripts.  We can safely exit here, for the dynamic
                   stack is already rewound. */
                exit(EX_SOFTWARE);
            } ...

exit()が呼び出されてアプリが強制終了してしまう。

あれこれ試してたところ、SCM_UNWIND_PROTECT を使えばいいことがわかった:

	SCM_UNWIND_PROTECT {
		ScmObj r = Scm_ApplyRec(Scm_SymbolValue(module, SCM_SYMBOL(SCM_INTERN("main"))), SCM_NIL);
	} SCM_WHEN_ERROR {
		printf("error\n");
	} SCM_END_PROTECT;

まだAPIが確定してないから勝手に使われると困るからドキュメント書かない、とかもわかるんだけどあれこれ手探りで探すの大変なので、将来変わってもいいから現在はこうなってるとかこう想定して作ってるとかいうメモ書きがあるといいなぁと思う。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090714

2009-07-12

w/uniq

Arcw/uniqのw/ってなんなのかよくわからなかったので覚えにくかったのだけど、w/はwithの意味なんですね。

(mac w/uniq (names . body)
  (if (acons names)
      `(with ,(apply + nil (map1 (fn (n) (list n '(uniq)))
                             names))
         ,@body)
      `(let ,names (uniq) ,@body)))
  • わざわざ + nil する意味がわからない…

call/cc は w 入ってないのに with の意味だな…不思議。

Gaucheの拡張ライブラリ作成

genstubでスタブ生成 - `(Hello ,world) - cadr groupで、genstub で作った拡張ライブラリのソースを直接プロジェクトに含めるとクラスのdllのリンケージが異なっていてエラーが出てしまう。なので別プロジェクトとしてdllを作成してやってみる。

dllのリンケージ指定

プリプロセッサでEXTSDL_EXPORTSと指定して、

#if defined(EXTSDL_EXPORTS)
#define LIBGAUCHE_EXT_BODY
#endif
#include <gauche/extern.h>      /* redefine SCM_EXTERN  */

とする。

dllのリンクエラー

自分で拡張ライブラリを作ろうとするとリンク時にエラーが出る:

リンクしています...
   ライブラリ D:\home\repos\lisp\gauche\sdlbind\Debug\ext-sdl.lib とオブジェクト D:\home\repos\lisp\gauche\sdlbind\Debug\ext-sdl.exp を作成中
sdl-lib.obj : error LNK2001: 外部シンボル "__imp__Scm_ProcedureClass" は未解決です。
sdl-lib.obj : error LNK2001: 外部シンボル "__imp__Scm_StringClass" は未解決です。
sdl-lib.obj : error LNK2019: 未解決の外部シンボル __imp__GC_malloc が関数 _sdl_lib_sdlrect_new で参照されました。
sdl-bind.obj : error LNK2001: 外部シンボル "__imp__GC_malloc" は未解決です。
sdl-lib.obj : error LNK2019: 未解決の外部シンボル __imp__Scm_Define が関数 _Scm_Init_sdl_lib で参照されました。
sdl-lib.obj : error LNK2019: 未解決の外部シンボル __imp__Scm_Intern が関数 _Scm_Init_sdl_lib で参照されました。
sdl-bind.obj : error LNK2001: 外部シンボル "__imp__Scm_Intern" は未解決です。
sdl-lib.obj : error LNK2019: 未解決の外部シンボル __imp__Scm_MakeString が関数 _Scm_Init_sdl_lib で参照されました。
sdl-bind.obj : error LNK2001: 外部シンボル "__imp__Scm_MakeString" は未解決です。
sdl-bind.obj : error LNK2001: 外部シンボル "__imp__Scm_ClassClass" は未解決です。
sdl-bind.obj : error LNK2019: 未解決の外部シンボル __imp__Scm_InitStaticClass が関数 _Scm_Init_SDL で参照されました。
sdl-bind.obj : error LNK2019: 未解決の外部シンボル __imp__Scm_FindModule が関数 _Scm_Init_SDL で参照されました。
D:\home\repos\lisp\gauche\sdlbind\Debug\ext-sdl.dll : fatal error LNK1120: 外部参照 9 が未解決です。
ビルドログは "file://d:\home\repos\lisp\gauche\sdlbind\Debug\BuildLog.htm" に保存されました。
ext-sdl - エラー 13、警告 0

これはプロジェクト依存関係でlibgaucheにチェックを入れればOK。

gauche-package generate

進めていくうちに、Gaucheではgauche-packageに拡張ライブラリを作るための作業を多少簡単にしてくれるコマンドがあることを知った。Gauche:拡張ライブラリ入門を参考に、

$ gauche-package generate sdl

とすると

などを作ってくれる。これを元に作っていったほうがいいだろう。

WinGaucheの拡張ライブラリの規則にのっとって、プロジェクト名はext-sdlとしよう。作成するdllの名前はsdlだと本当のsdlとかぶってしまうのでgauche-sdl.dllとしよう。そうするとdllのエントリ名も合わせる必要があるので、

SCM_EXTENSION_ENTRY void Scm_Init_gauche_sdl(void)

とする。

GAUCHE_API_0_9

スタブから.cの生成は、ラベルGAUCHE_API_0_9を定義させるために

$ gosh genstub -D GAUCHE_API_0_9 sdl-bind.stub

とする。

Cの構造体に対応するSchemeのクラス定義

構造体の定義は、スタブに

(define-cclass <SDL_Rect> "ScmSDL_Rect*" "Scm_SDL_RectClass"
  ()
  ((x :type <short> :setter "obj->rc.x = (short)SCM_INT_VALUE(value);" :getter "return SCM_MAKE_INT(obj->rc.x);")
   ...)
  (allocator (c "alloc_SDL_Rect")))

などと書く。スロットの定義を書けばSchemeからslot-refやslot-set!でアクセスできるようになる。

cclassの定義に親クラスを書かないとSCM_CLASS_DEFAULT_CPLを参照するようになってるが、VCだと外部dllの実体の参照が静的に置けないのでSCM_DEFINE_BUILTIN_CLASSでエラーが出てしまう。なので親クラステーブルをNULLとするためスタブに

#undef SCM_CLASS_DEFAULT_CPL
#define SCM_CLASS_DEFAULT_CPL NULL

を挿入しておく。

ForeignPointer

SDL_Surfaceのように、ポインタだけでScheme側からは中身に直接触らないものはScm_MakeForeignPointerClassを使って

ScmClass *Scm_SDL_SurfaceClass;
	Scm_SDL_SurfaceClass = Scm_MakeForeignPointerClass(mod, "<SDL_SurfacePtr>", SDL_SurfacePtr_print, SDL_SurfacePtr_cleanup, SCM_FOREIGN_POINTER_KEEP_IDENTITY|SCM_FOREIGN_POINTER_MAP_NULL);

などと書く。

gauche-init.scm

以前やったときに(use)が使えなかったのは起動時にgauche-init.scmを読み込めば解決した。これを読み込まないとuvectorを使おうとしたときにエラーが出て気がついた。gauche-init.scmはgoshなどでも起動時に読まれるスクリプト。

こんなところかな…。ドキュメントとしてまとまってないのでググッたり他の拡張ライブラリ見たり推測したり大変だった。誰かまとめないですかね。

ソース

以下、SDLの拡張ライブラリを使ってキー操作でスプライトを動かすテスト:

続きを読む

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090712

2009-07-10

Cygwin版Gaucheでc-wrapperをビルドしてみる

やっぱり使ってたGaucheWindows用だった。Cygwin上でGaucheをソースからビルドしてインストール、そしてc-wrapperをビルドしてみた。configureはちゃんとできた。makeするとリンクエラーが出る:

$ make
...
gcc -std=gnu99  -L/usr/local/lib/gauche/0.8.14/i686-pc-cygwin  -Wl,--export-all-
symbols -Wl,--enable-auto-import -shared -o c-parser.dll 'c-parser_head.o' 'c-pa
rser.o' 'c-parserlib.o' 'c-parser_tail.o' -lgauche -lm  -lpthread libffi/.libs/l
ibffi.a -lgauche-uvector
c-parser.o:c-parser.c:(.text+0x6c8): undefined reference to `_Scm_CStructSymbol'
c-parser.o:c-parser.c:(.text+0x73d): undefined reference to `_Scm_CUnionSymbol'
c-parser.o:c-parser.c:(.text+0x1979): undefined reference to `_Scm_ParserAttributeRef'
c-parser.o:c-parser.c:(.text+0x198a): undefined reference to `_Scm_ParserAttributeClear'
c-parser.o:c-parser.c:(.text+0x1ab6): undefined reference to `_Scm_ParserAttributeClear'
c-parser.o:c-parser.c:(.text+0x2986): undefined reference to `_Scm_FilenameRef'
c-parser.o:c-parser.c:(.text+0x2b8c): undefined reference to `_Scm_CStructSymbol'
c-parser.o:c-parser.c:(.text+0x2c15): undefined reference to `_Scm_CStructSymbol'
c-parser.o:c-parser.c:(.text+0x2c43): undefined reference to `_Scm_CStructSymbol'
c-parser.o:c-parser.c:(.text+0x2ced): undefined reference to `_Scm_CUnionSymbol'
c-parser.o:c-parser.c:(.text+0x2d76): undefined reference to `_Scm_CUnionSymbol'
c-parser.o:c-parser.c:(.text+0x2da4): undefined reference to `_Scm_CUnionSymbol'
c-parser.o:c-parser.c:(.text+0x316d): undefined reference to `_Scm_InstallType'
c-parser.o:c-parser.c:(.text+0x3188): undefined reference to `_Scm_CStructSymbol'
c-parser.o:c-parser.c:(.text+0x3602): undefined reference to `_Scm_InstallType'
c-parser.o:c-parser.c:(.text+0x3887): undefined reference to `_Scm_ParserAttributeClear'
c-parser.o:c-parser.c:(.text+0x394a): undefined reference to `_Scm_StartMacroSet'
c-parser.o:c-parser.c:(.text+0x3956): undefined reference to `_Scm_LastTokenSet'
c-parser.o:c-parser.c:(.text+0x39a8): undefined reference to `_Scm_SetInputString'
c-parser.o:c-parser.c:(.text+0x3c47): undefined reference to `_Scm_FilenameSet'
c-parser.o:c-parser.c:(.text+0x3c5a): undefined reference to `_Scm_LineNumberSet'
c-parser.o:c-parser.c:(.text+0xbbb1): undefined reference to `_Scm_CScan'
collect2: ld returned 1 exit status
*** ERROR: command execution failed: gcc -std=gnu99  -L/usr/local/lib/gauche/0.8
.14/i686-pc-cygwin  -Wl,--export-all-symbols -Wl,--enable-auto-import -shared -o
 c-parser.dll 'c-parser_head.o' 'c-parser.o' 'c-parserlib.o' 'c-parser_tail.o' -
lgauche -lm  -lpthread libffi/.libs/libffi.a -lgauche-uvector
Stack Trace:
_______________________________________
  0  args

  1  (usage)
        At line 101 of "(input string port)"
make[1]: *** [c-parser.dll] Error 70
make[1]: Leaving directory `/cygdrive/d/home/repos/lisp/gauche/c-wrapper-0.6.0/s
rc'
make: *** [all] Error 2

gauche-packageがコケてるぽい

c-wrapperがCygwinでビルドできなかったので、試しにGauche-glもやってみるとconfigureで同じようにエラーが出て:

$ ./configure
...
checking for gzip... gzip
configure: creating Gauche-gl.gpd
*** ERROR: string required, but got #f
Stack Trace:
_______________________________________
  0  (build-path (home-directory) ".gauche-package")
        At line 88 of "(input string port)"
  1  (read-config)
        At line 97 of "(input string port)"
configure: creating ./config.status
...

makeでも同じメッセージが出た:

$ make
cd src; make all
make[1]: Entering directory `/cygdrive/d/home/repos/lisp/gauche/Gauche-gl-0.4.4/
src'
/usr/local/bin/gauche-package compile --verbose \
   --cflags="-DPACKAGE_NAME=\"Gauche-gl\" -DPACKAGE_TARNAME=\"gauche-gl\" -DPACK
AGE_VERSION=\"0.4.4\" -DPACKAGE_STRING=\"Gauche-gl\ 0.4.4\" -DPACKAGE_BUGREPORT=
\"shiro@acm.org\"   " --ldflags="" --libs="-lgauche-uvector " \
   libgauche-math3d gauche-math3d.c math3d-lib.stub
*** ERROR: string required, but got #f
Stack Trace:
_______________________________________
  0  (build-path (home-directory) ".gauche-package")
        At line 88 of "(input string port)"
  1  (read-config)
        At line 97 of "(input string port)"
make[1]: *** [libgauche-math3d.dll] Error 70
make[1]: Leaving directory `/cygdrive/d/home/repos/lisp/gauche/Gauche-gl-0.4.4/s
rc'
make: *** [all] Error 2

怪しいと思って、gauche-packageというのを単体で実行しても同じエラー:

$ gauche-package.exe
*** ERROR: string required, but got #f
Stack Trace:
_______________________________________
  0  (build-path (home-directory) ".gauche-package")
        At line 88 of "(input string port)"
  1  (read-config)
        At line 97 of "(input string port)"

home-directoryだかbuild-pathがまずそう。

具体的には(home-directory)が#fを返すためにそこでmakeが止まります

403 Forbidden

使ってるGaucheコンパイル済Windows用バイナリだっけか?Cygwin上で自分でビルドしてインストールすればうまくいくかしらん。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090710

2009-07-09

Squirrelの末尾再帰

Squirrel3α2 で無限forループの中からreturnで無理やり別の関数を末尾呼び出ししてもスタック溢れずに動くことを確認:

function state0() {
	for (;;) {
		print("state0\n");
		if (rand() * 100 / (RAND_MAX+1) < 2) {
			return state1();
		}
	}
}

function state1() {
	for (;;) {
		print("state1\n");
		if (rand() * 100 / (RAND_MAX+1) < 2) {
			return state0();
		}
	}
}

srand(time());

state0();

Schemeだとreturnとか書けないから、脱出用の継続を使ってということになるかな:

(define-macro (forever . body)
  (let1 next (gensym)
    `(let1 ,next (call/cc
                  (lambda (return)
                    (while #t
                      ,@body)))
       (,next))))

(use srfi-27)  ; random

(define (state0)
  (forever
   (print "state0")
   (when (< (random-real) 0.02)
     (return state1))))

(define (state1)
  (forever
   (print "state1")
   (when (< (random-real) 0.02)
     (return state0))))

(state0)
  • returnに次に呼び出すプロシジャを渡して、外で呼び出す

genstubでスタブ生成

Gauche:MeCabを模倣。このページにCの構造体をGaucheのクラスにマップするやり方が書いてある。

例えばSDL_Rectだったら、sdl.stubというファイル

"
 #include <gauche/extend.h>
 #include <SDL/SDL.h>

 typedef struct ScmSDL_RectRec {
   SCM_HEADER;
   SDL_Rect rc;
 } ScmSDL_Rect;

 SCM_CLASS_DECL(Scm_SDL_RectClass);
 #define SCM_CLASS_SDL_RECT (&Scm_SDL_RectClass)
 #define SCM_SDL_RECT(obj) ((ScmSDL_Rect*)(obj))
 #define SCM_SDL_RECTP(obj) (SCM_XTYPEP(obj, SCM_CLASS_SDL_RECT))

 /* Hack for initialization stub */
 static void internal_init(ScmModule*);
 void Scm_Init_sdl(void)
 {
   ScmModule *mod;
   SCM_INIT_EXTENSION(sdlrect);
   mod = SCM_MODULE(SCM_FIND_MODULE(\"sdl\", TRUE));
   internal_init(mod);
 }
 #define Scm_Init_sdl internal_init
"

(define-cclass <sdlrect> "ScmSDL_Rect*" "Scm_SDL_RectClass"
  ()
  ())

(define-cproc sdlrect-new ()
  "  ScmSDL_Rect *m = SCM_NEW(ScmSDL_Rect);
  SCM_SET_CLASS(m, SCM_CLASS_SDL_RECT);
  SCM_RETURN(SCM_OBJ(m));")

を作る。定義したい構造体の頭に SCM_HEADER という共通の要素を置いて、実際の中身を続ける。元のページだとSCM_MODULEに渡す部分の「¥」がエスケープされて「?"mecab?"」というようになってしまっている。

これをgenstubで変換する:

gosh genstub sdl.stub

sdl.cというファイル

/* Generated by genstub.  Do not edit. */
#include <gauche.h>

 #include <gauche/extend.h>
 #include <SDL/SDL.h>

 typedef struct ScmSDL_RectRec {
   SCM_HEADER;
   SDL_Rect rc;
 } ScmSDL_Rect;

 SCM_CLASS_DECL(Scm_SDL_RectClass);
 #define SCM_CLASS_SDL_RECT (&Scm_SDL_RectClass)
 #define SCM_SDL_RECT(obj) ((ScmSDL_Rect*)(obj))
 #define SCM_SDL_RECTP(obj) (SCM_XTYPEP(obj, SCM_CLASS_SDL_RECT))

 /* Hack for initialization stub */
 static void internal_init(ScmModule*);
 void Scm_Init_sdl(void)
 {
   ScmModule *mod;
   SCM_INIT_EXTENSION(sdlrect);
   mod = SCM_MODULE(SCM_FIND_MODULE("sdlrect", TRUE));
   internal_init(mod);
 }
 #define Scm_Init_sdl internal_init

#if defined(__CYGWIN__) || defined(GAUCHE_WINDOWS)
#define SCM_CGEN_CONST /*empty*/
#else
#define SCM_CGEN_CONST const
#endif
static SCM_CGEN_CONST struct scm__scRec {
  ScmString d742[1];
} scm__sc = {
  {   /* ScmString d742 */
      SCM_STRING_CONST_INITIALIZER("sdlrect-new", 11, 11),
  },
};
SCM_DEFINE_BUILTIN_CLASS(Scm_SDL_RectClass, NULL, NULL, NULL, NULL, SCM_CLASS_DEFAULT_CPL);

static ScmObj sdl_sdlrect_new(ScmObj *SCM_FP, int SCM_ARGCNT, void *data_)
{
  SCM_ENTER_SUBR("sdlrect-new");
  {
  ScmSDL_Rect *m = SCM_NEW(ScmSDL_Rect);
  SCM_SET_CLASS(m, SCM_CLASS_SDL_RECT);
  SCM_RETURN(SCM_OBJ(m));
  }
}

static SCM_DEFINE_SUBR(sdl_sdlrect_new__STUB, 0, 0, SCM_OBJ(&scm__sc.d742[0]), sdl_sdlrect_new, NULL, NULL);

void Scm_Init_sdl(ScmModule *mod)
{

  Scm_InitBuiltinClass(&Scm_SDL_RectClass, "<sdlrect>", NULL, TRUE, mod);
  SCM_DEFINE(mod, "sdlrect-new", SCM_OBJ(&sdl_sdlrect_new__STUB));
}

が生成される。うーん、こうやって構造体1個ごとに定義していくのは面倒すぎる。なんとかならないもんか。指定サイズのuvectorを確保して中身をCの任意の型として読み書きできるとかでいいんだけど。

ただこれをVCのプロジェクトに追加してコンパイルすると

sdlrect.c
d:\home\repos\lisp\gauche\sdlbind\src\sdl.c(40) : warning C4273: 'Scm_SDL_RectClass' : dll リンクが一貫していません。
        d:\home\repos\lisp\gauche\sdlbind\src\sdl.c(12) : 'Scm_SDL_RectClass' の前の定義を確認してください

というワーニングが出て、リンクにも失敗する:

リンクしています...
   ライブラリ D:\home\repos\lisp\gauche\sdlbind\Debug\sdlbind.lib とオブジェクト D:\home\repos\lisp\gauche\sdlbind\Debug\sdlbind.exp を作成中
MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。
sdl.obj : error LNK2001: 外部シンボル "_Scm_DefaultCPL" は未解決です。
D:\home\repos\lisp\gauche\sdlbind\Debug\sdlbind.exe : fatal error LNK1120: 外部参照 1 が未解決です。

拡張モジュールは別プロジェクトにしてDLLを作らないとだめなんだろうか。

Gaucheドキュメントしっかりしてるのに、C APIとか拡張モジュールの作り方とかgenstubのドキュメントがほとんど整備されてないのは意図してやってるんだろうか。

参考になりそうなリンク:

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090709

2009-07-08

ここまでのソース

貼っておかないとなくすから

  • not equalは一般的にはどうするのかな?
  • Arcifletを取り入れてみた

entry.scm:

(define (/= a b) (not (= a b)))

(define-macro (iflet var val then . rest)
  (let1 g (gensym)
    `(let1 ,g ,val
       (if ,g
           (let1 ,var ,g
             ,then)
         ,@rest))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define-constant FRAME_TICKS 16) ;(div 1000 60))
(define-constant ScreenWidth 640)
(define-constant ScreenHeight 480)

(define *screen* '())
(define videoflags '())
(define sprite '())

(define (load-image fn)
  (iflet surface (SDL_LoadBMP fn)
      (iflet converted (SDL_DisplayFormat surface)
          (begin
            (SDL_FreeSurface surface)
            converted)
        surface)
    #f))

(define (term)
  (SDL_Quit))

(define (init caption w h)
  (if (< (SDL_Init SDL_INIT_VIDEO) 0)
      #f
    (begin
      (SDL_WM_SetCaption caption '())

      (set! videoflags (logior SDL_HWSURFACE SDL_DOUBLEBUF))
      (set! *screen* (SDL_SetVideoMode w h 32 videoflags))
      *screen*)))

(define wait
  (let ((lastticks '()))
    (lambda (frame_ticks)
      (let1 ticks (SDL_GetTicks)
        (unless (null? lastticks)
          (let1 d (- frame_ticks (- ticks lastticks))
            (when (> d 0)
              (SDL_Delay d))))
        (set! lastticks ticks)))))

(define (loop)
  (let ((x 100)
        (y 100)
        (vx 2)
        (vy 2))
    (while (proc_events)
      (SDL_FillRect *screen* '() 0)
      (inc! x vx)
      (inc! y vy)
      (when (or (< x 0) (>= x ScreenWidth))
        (set! vx (- vx)))
      (when (or (< y 0) (>= y ScreenHeight))
        (set! vy (- vy)))
      (SDL_BlitSurface sprite '() *screen* x y)
      (wait FRAME_TICKS)
      (SDL_Flip *screen*))))

(define (main)
  (if (init "SDL Test" ScreenWidth ScreenHeight)
      (begin
        (set! sprite (load-image "icon.bmp"))
        (loop)
        (term))
    (print "初期化失敗")))

(main)

続きを読む

Cの構造体をGauche側からどうやって渡すのか

c-wrapper を使わずに地味に SDL への呼び出しを書いてるところ。SDL_BlitSurface に渡す SDL_Rect は、Gauche 側からどうやって渡すのかで詰まってる。

Ypsilonではmake-bytevectorで領域を確保してそれを渡すっぽい(紫ログ:なあ、moshでもMeCabを使ってみようか - livedoor Blog(ブログ))けど、Gaucheだとどうやるんだろう?

一時的に使うメモリだったらスタック上に確保できる方法とかあったら嬉しい。

参考になりそうなリンク:

hchbawhchbaw2009/07/09 14:36こんにちは、はじめまして!言及されたのに反応しました!

自分なら Gauche 側から触りやすくするために <SDL_Rect> などと定義しちゃいます。でもこれひとつひとつやっつけてゆくのって退屈なんですよね。そこで c-wrapper、となるのでしょうね。で試しに epeg でやってみたらば、(use c-wrapper) (c-load '("Epeg.h")) だけでマッピングやらなにやら全て終っちゃいました。(^^;

mokehehemokehehe2009/07/10 00:38c-wrapperすごいですね。どうやってるのか仕組みを知りたいところです。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090708

2009-07-06

c-wrapperをcygwinから使おうとするとビルドでエラー

使ったのはc-wrapper0.6.0。./configure の途中でエラーが出てる:

...
checking for ldconfig... no
configure: creating c-wrapper.gpd
*** ERROR: string required, but got #f
Stack Trace:
_______________________________________
  0  (build-path (home-directory) ".gauche-package")
        At line 88 of "(input string port)"
  1  (read-config)
        At line 97 of "(input string port)"
configure: creating ./config.status
...

でも残りは成功してMakefileはできてる。make

...
/usr/local/bin/gauche-package compile --cppflags="-I./libffi/include -DGAUCHE_AP
I_0_8_8 " --ldflags="" --libs="libffi/.libs/libffi.a -lgauche-uvector " --verbos
e c-ffi c-ffi.c c-ffilib.stub closure_alloc.c
*** ERROR: string required, but got #f
Stack Trace:
_______________________________________
  0  (build-path (home-directory) ".gauche-package")
        At line 88 of "(input string port)"
  1  (read-config)
        At line 97 of "(input string port)"
make[1]: *** [c-ffi.dll] Error 70
make[1]: Leaving directory `/cygdrive/c/temp/c-wrapper-0.6.0/src'
make: *** [all] Error 2

わからない…

Gauche0.8.14をVC2008でビルドする

なんか毎回初めから挑戦しなおしてる気がする。

手始めにCygwinでビルド。最近はCygwinでビルドしようとするとなぜか configure の段階で「C compiler cannot create executable」とか出て困ってた。configure.log を見たら、単に環境変数 LIBS に Windows のパスが設定されていてあらぬエラーを引き起こしていただけだった。LIBS を空にしてビルド:

  • ./configure
  • シンボリックリンクがないので、gc/libatomic_ops-1.2 を libatomic_ops にリネーム(同名の空ファイル(シンボリックリンクの残骸?)があるので削除してから)
  • make

できた。次はVC2008でビルドする:

  • winnt ディレクトリにGauche.slnがあるのでVCで開く。
  • gc/include/gc.h で _beginthread などのマクロを定義しているがシステムの process.h とぶつかるので、先にprocess.hをincludeするようにする
...
# ifndef GC_NO_THREAD_REDIRECTS
#  ifdef _MSC_VER
#   include <process.h>
#  endif
#   define CreateThread GC_CreateThread
...
  • libgaucheの「追加のインクルードディレクトリ」に「..\gc\libatomic_ops\src」を追加
  • ext/net/gauche/net.hでinet_pton, inet_ntopが既定義エラーが出るので、コメントアウト
#if !(NTDDI_VERSION >= NTDDI_LONGHORN)
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
#endif
  • ext-digest-md5のプロジェクトに含まれるmd5.cがないのでプロジェクトから削除
  • ext-digest-sha1のプロジェクトに含まれるsha1.cがないのでプロジェクトから削除

でビルドに成功、winnt/Debugにlibgauche.lib,dllやgosh.exeなどができる。

プロジェクトgoshを「スタートアップ プロジェクトに設定」して実行する:

gosh: WARNING: Error while loading initialization file: cannot find file "gauche
-init.scm" in *load-path* ("/usr/local/share/gauche/site/lib" "/usr/local/share/
gauche/0.8.14/lib")(error).

というエラーが出る。

  • src/gauche/arch.h内のGAUCHE_LIB_DIR, GAUCHE_SITE_LIB_DIRをなどを修正する
#define GAUCHE_ARCH "i686-pc-cygwin"
#define GAUCHE_LIB_DIR "C:\\cygwin\\usr\\local\\share\\gauche\\0.8.14\\lib"
#define GAUCHE_ARCH_DIR "C:\\cygwin\\usr\\local\\lib\\gauche\\0.8.14\\i686-pc-cygwin"
#define GAUCHE_SITE_LIB_DIR "C:\\cygwin\\usr\\local\\share\\gauche\\site\\lib"
#define GAUCHE_SITE_ARCH_DIR "C:\\cygwin\\usr\\local\\lib\\gauche\\site\\0.8.14\\i686-pc-cygwin"
  • whileや、(use srfi-1)も普通に使えた
  • 毎回フルビルドがかかる。ビルドイベントの「ビルド前のイベント」に「cscript configure.js」が入ってるけど、毎回winnt/gauche/config.hが作られてしまうので「ビルドから除外」を「はい」にする
追記

winnt/winvc-prep.sh の実行を忘れてた

  • シェルから sh winnt/winvc-prep.sh を実行する
    • configureが行われて、src/gauche/arch.hも作られる
  • ビルド
  • winnt/share/gauche というディレクトリを掘って C:\cygwin\usr\local\share\gauche の中身をコピー
  • winnt/lib/gauche/site/0.8.14/i686-pc-winnt というディレクトリを掘って winnt/(Debug|Release)/*.dll をコピー
Release版は設定がちゃんとされてない
  • すべてのプロジェクトの「中間ディレクトリ」を「$(ProjectName)\$(ConfigurationName)」にする
  • libgaucheのプロパティの「追加のインクルードディレクトリ」と「プリプロセッサの定義」と「リンカ/追加の依存ファイル」をDebug版とあわせる
  • libgauche/srcのbuiltin-syms.c, dl_win.c, getdir_win.cを「ビルドから除外」を「はい」にする
  • gosh, test-vmstack, test-arithの「追加のインクルードディレクトリ」をDebug版とあわせる
  • ext-charconvの「プリコンパイル済みヘッダーの作成/使用」を「使用しない」にする
    • eucj2ucs.c, guess_tab.c, ucs2eucj.c を「ビルドから除外」
  • ext-auxsys, ext-net, gauche-configの「リンカ/追加の依存ファイル」をDebug版とあわせる

ext-netとext-charconvで_imp__Scm_StringClassがどうのというエラーが取れない…

------ ビルド開始: プロジェクト: ext-net, 構成: Release Win32 ------
リンクしています...
warning C4743: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\netaux.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\addr.c' 内で異なるサイズを含んでいます: 4 および 100 バイト
warning C4744: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\netaux.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\addr.c' 内で異なる型を含んでいます: 'pointer' および 'struct (100 bytes)'
warning C4743: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\netlib.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\addr.c' 内で異なるサイズを含んでいます: 4 および 100 バイト
warning C4744: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\netlib.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\net\addr.c' 内で異なる型を含んでいます: 'pointer' および 'struct (100 bytes)'
addr.obj : error LNK2001: 外部シンボル "_Scm_StringClass" は未解決です。
D:\gauche\Gauche-0.8.14\winnt\Release\ext-net.dll : fatal error LNK1120: 外部参照 1 が未解決です。

------ ビルド開始: プロジェクト: ext-charconv, 構成: Release Win32 ------
リンクしています...
warning C4743: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\convaux.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\charconv.c' 内で異なるサイズを含んでいます: 4 および 100 バイト
warning C4744: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\convaux.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\charconv.c' 内で異なる型を含んでいます: 'pointer' および 'struct (100 bytes)'
warning C4743: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\convlib.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\charconv.c' 内で異なるサイズを含んでいます: 4 および 100 バイト
warning C4744: '_imp__Scm_StringClass' は、'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\convlib.c' および 'd:\home\repos\lisp\gauche\Gauche-0.8.14\ext\charconv\charconv.c' 内で異なる型を含んでいます: 'pointer' および 'struct (100 bytes)'
charconv.obj : error LNK2001: 外部シンボル "_Scm_StringClass" は未解決です。
D:\gauche\Gauche-0.8.14\winnt\Release\ext-charconv.dll : fatal error LNK1120: 外部参照 1 が未解決です。

masa_edwmasa_edw2009/07/07 11:52結局mingwのSDLをcygwinのc-wrapperから使うことはあの時点で諦めてその後挑戦していませんでした。c-wrapper-0.5.5自体はcygwin上でビルドできていました。0.6.0では試していません。cygcheckはdllの依存性を確かめるツールです(dllに対しても使えます)。Linuxでいうところのlddのようなものです。

mokehehemokehehe2009/07/07 21:03Windows環境で使うのは難しそうですね。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090706