Hatena::Grouptemtan

End of Dary

2012-07-21

[]toxyzzy その5 14:22 toxyzzy その5 - End of Dary を含むブックマーク はてなブックマーク - toxyzzy その5 - End of Dary

続き。

ということで、lisp 上で使う win32api の宣言をする lisp を書き始める。この辺からコードを書き始める感じなのだけど、まだ設計はしていない事になる。といっても頭の中ではもう大体設計してるので、まだちゃんと整理して過不足なく網羅できてるかどうかをしてないという意味ではある。

んで、書いた lisp はこんな感じ。

;; toxyzzy

(provide "toxyzzy")
(in-package "winapi")

(require "wip/winapi")

;; typedef -----
(c:define-c-type (DWORD *) LPDWORD)
(c:define-c-type ULONG ULONG_PTR)

;; struct -----
(c:define-c-struct SECURITY_ATTRIBUTES
  (DWORD  nLength)
  (LPVOID lpSecurityDescriptor)
  (BOOL   bInheritHandle))
(c:define-c-type (SECURITY_ATTRIBUTES *) LPSECURITY_ATTRIBUTES)

(c:define-c-struct OVERLAPPED
  (ULONG_PTR Internal)
  (ULONG_PTR InternalHigh)
  (DWORD   Offset)
  (DWORD   OffsetHigh)
  (HANDLE  hEvent)
  )
(c:define-c-type (OVERLAPPED *) LPOVERLAPPED)

;; function -----
(c:define-dll-entry
  HANDLE
  CreateNamedPipeA
  (LPCSTR
   DWORD
   DWORD
   DWORD
   DWORD
   DWORD
   DWORD
   LPSECURITY_ATTRIBUTES
   )
  "kernel32.dll"
  )

(c:define-dll-entry
  BOOL
  ConnectNamedPipe
  (HANDLE
   LPOVERLAPPED
   )
  "kernel32.dll"
  )

(c:define-dll-entry
  DWORD
  WaitForSingleObject
  (HANDLE
   DWORD
   )
  "kernel32.dll"
  )

(c:define-dll-entry
  BOOL
  ReadFile
  (HANDLE
   LPVOID
   DWORD
   LPDWORD
   LPOVERLAPPED
   )
  "kernel32.dll"
  )

(c:define-dll-entry
  BOOL
  CloseHandle
  (HANDLE)
  "kernel32.dll"
  )

これを書く過程で、provide とか in-package について調べたりした。調べてから以前調べたような覚えがあったけど忘れてたので、また調べてる感覚が出てきた。

と、この辺が出来た所で設計的なのを始める。処理の大まかな流れとポイントとなる関数を紙に書いて整理する。まあ今回はかなり小さいプログラムなのですぐに終わったわけで。まあこんなもん。あと、ついでと言ってはアレだけど、機能とかオプションのバリエーションを色々と考えてメモもしておく。出力するバッファを事前に設定しておくとか、起動する度に新しいバッファを作る設定とか色々。

その辺整理が終わったので本格的にコードを書くことに。とりあえずは C 側の main 関数のベースの定型的なセット、要するにプロジェクトファイルとかその設定を色々したり、自作の汎用ライブラリを用意したりとね。今日はそこまでーって感じ。

2012-07-19

[]toxyzzy その4 23:26 toxyzzy その4 - End of Dary を含むブックマーク はてなブックマーク - toxyzzy その4 - End of Dary

続き

ちょこちょこっと調べていたら以下のサイトを発見

no title

要するに lisp 側から C の関数を呼び出すための仕組みの紹介。まさに今の自分にピッタリ。

ということでとりあえず以下を順番に出来るようにやってみた

  • GetLastError を呼び出す
  • MessageBox を呼び出す
    • 次によく使う文字列引数に含まれている為。
    • あと MessageBox 関数は実体ではなく実体は MessageBoxA または MessageBoxW なので注意が必要
    • dll は user32.dll

この辺は実行して出来るようになった。この調子でいけば名前付きパイプを使う上で必要な関数は呼び出せるだろうから、この辺の調査はとりあえず止め。

次に、名前付きパイプを使う上で定義する必要のある構造体や関数をちょいちょいと調べる。自分が機能として欲しいのを考えて調べると

  • CreateNamedPipeA
  • ConnectNamedPipe

は、まあ基本。 ConnectNamedPipe 関数はエラーとかの場合制御が戻って来ない可能性があるので非同期的に動作させる必要があるっぽいので、その場合以下も必要かな。

  • OVERLAPPED
  • WaitForSingleObject

データの受け取りに必要なのは

  • ReadFile

と、色々と自分で定義する必要があって面倒だナーと思ってた所に調べてたらなんと xyzzylispライブラリwin/winapi.l ってのがあるようじゃないですか。ここには基本的な型とか構造体とか関数が既に定義されてるようなのでこれはありがたいー。

ということで次にやるのは、これを使って関数と構造体の定義をするのカナーといった感じに。

2012-07-18

[]toxyzzy その3 00:22 toxyzzy その3 - End of Dary を含むブックマーク はてなブックマーク - toxyzzy その3 - End of Dary

続き

結局色々考えると自分がやりたいのは「非同期でバッファにデータ入力をする」をしたいのだけど、xyzzylisp ではマルチスレッドが無いので出来ないっぽい。 C 側でスレッドを作っても、 C 側から lisp を操作する必要があるが、その方法は非常に難しい(ソースを解析レベル)

他の案として

  • 非同期(スレッドではなく)プロセスを使う
    • プロセスが終わってからデータを取るっぽくて駄目っぽい
  • start-timer を使う
    • 文字通りタイマーでしかなく、定期的に何か叩くとかコスト高いというか駄目だろー

とか考えたけど結局駄目な感じで、しょうがないのでこの方向性はあきらめる事に。

んで、代案として考えていたのが、一度データをファイルに書き出してからそれを xyzzycli.exe引数に渡してそのファイルを開くというやり方。ファイル経由でゴミが残りそうだし、正直ビミョーな感じなのだけど、背に腹は代えられない訳でとりあえずこちら方面で考える事に。

と、こっち方面に行くことにしたので、この辺で UI とかの事も考えての調査に。まずは xyzzycli.exe の使い方。まあ引数にファイルを渡せば良いのだけど、その辺熟知していると使い勝手が大幅に良くなったりするのでこういった調査は欠かせない。

と、xyzzy の 00README.html を見ていたら、なんと -l とか -f とか -e とかが lisp を実行するオプションじゃないですか。コレで行ける。 xyzzycli.exexyzzy に名前付きパイプを作らせて待ち受けさせてそこにデータを流し込む。うむコレ行ける。

ということで、あきらめた名前付きパイプを使う方法があっさり復活しました。若干最初に考えてた方法とは違うけど、タイムアウト時間とか考えれば固まる事も無いし充分に許容範囲内。

ということで大体の方式はまとまったので、次のレベルの詳細で出来るかどうか判らない部分の調査かなー。つまり、lisp 側から C の関数を呼ぶあたりらへん。この辺が出来るようになったら、本格的な設計かなー。

2012-07-17

[]to_xyzzy その2 23:42 to_xyzzy その2 - End of Dary を含むブックマーク はてなブックマーク - to_xyzzy その2 - End of Dary

昨日の続き。

名前付きパイプを使うのは用途とか考えるとほぼこれが正解っぽいのでコレで行く方向で。

そうなると呼び出す必要が有るWIN32API関数は以下

  • CreateNamedPipe
  • ConnectNamedPipe

これらの関数xyzzyプロセス側から呼び出す必要があり、lisp 側で使う必要がある。となると以下の2通りの案が出来るかどうか調査する

  • xyzzy に名前付きパイプを使う lisp関数群が用意されているので
  • 上記が無いので C の dll 関数を呼び出す lisp 関数を使ってそれを作る

ざっと xyzzylisp とかソースを調べたのだけど名前付きパイプを使う為の用意は無かったので後者の自作する必要があるようだった。

C の dll 関数を呼び出すには以下の lisp 関数が軸になっているっぽい

  • define-dll-entry
  • si:make-c-function
  • si:load-dll-module

この辺について詳しく調べる必要があるっぽい。

と、この辺で調査がちょいと飽きたので、名前付きパイプ関連は置いておいて、それらを待ち受ける必要があって、待ち受けの為には別にスレッドを起こす必要があるっぽいので、 lispスレッドを作るとかの機能はあるだろうと高をくくっていたのだけど、調べたらどうも無いみたいです。無いみたい。これは参った。

今までは、待ち受け用のスレッドを作ってそこで名前付きパイプに繋がるのを待ち受ける感じで設計を考えていたのだが、コレが出来ないとなるとそもそものその辺の設計というか使い方から考え直さないといけなくて、そうなるとそれって結局クリップボード経由とたいして手間が変わらないよねーってなってしまい兼ねなくて、計画が頓挫してしまう。けど、lisp 側でマルチスレッドを使えないとどうしようも無い。

マルチスレッドを扱えるようにするには C 側でどうにかする必要があるのだが、C 側から lisp の操作って出来るかどうかわからんし、出来ても相当に危険っちゃ危険。むむむむ。

とりあえずは、C 側から lisp を操作する方向性かな。それなら名前付きパイプの扱いも C 側から出来るのでその辺考慮する必要が無い。しかし思ったよりも変な感じになって来たなあ。

2012-07-16

[]標準入力xyzzy に転送するプログラム 23:43 標準入力を xyzzy に転送するプログラム - End of Dary を含むブックマーク はてなブックマーク - 標準入力を xyzzy に転送するプログラム - End of Dary

以前からあったら便利かナーって思ってたプログラムがあったけど、作り方が良くわからなかったのであきらめてたけど、最近行けるかもしれないと思った訳で、それが標準入力xyzzy に転送するプログラムであります。

んで、できるかどうかわからないのだけど、せっかくなので思考を整理したりする過程をメモがてら公開してみようかなとか。絵描きがラフを公開する感じで。

目的の機能

どう作るか

  • 大まかに分けて以下を作る必要アリ
  • 標準入力からのデータ取得について
  • xyzzy プロセスへデータの転送について
    • プロセス間通信なわけだけど使用する方法が複数あるので選択
    • 簡単なのはパイプだけど、xyzzy の使い方を考えると使えない
    • 名前付きパイプなら事前に設定して wait すれば良さそうである
    • ソケットとかにすると何というかやり過ぎというかなんか違う感じがする
    • 共有メモリも同じく
    • なので名前付きパイプの方向
    • この辺は xyzzy 側で出来ないといけないので以下が xyzzylisp で出来ないと困る
      • 名前付きパイプを開く
      • WaitForSingleObject() 相当
      • 常駐する感じなのかなー
      • 後始末とか色々?
  • データを xyzzyバッファへ書き込むについて
    • バッファの指定位置の指定
    • データを write する

今のところのキモは xyzzylisp で名前付きパイプが扱えるかどうかかな。ただ open して wait かければいいのかしら。

名前は toxyzzy か to_xyzzy かなー。