著作一覧 |
途中だけど、とりあえずここまでかな。
GainerX(2014/7/30 レポジトリをGitHubへ移動)最初、オーバーラップトIOのみで1バイト単位のReadFileを利用していたが、アナログ/デジタル連続リードをかけると取りこぼしやすいことがわかったので、ComEventを利用してできる限り一括してReadFileをかけるようにした。ほぼ取りこぼしはなくなっている(VB6の場合)。
VS2008になっても、相変わらず、SAFEARRAY周りの処理が腐っているので絶望した。きっとこのまま直さないままATLはフェーズアウトしていくのかも。
たとえば、IDLで、[in]SAFEARRAY(byte) data
と書いたものが、自動生成した接続ポイント(しかし、VC6の頃と比べて使われるのを拒否するかのように、わけのわからない場所に移動してしまって見つけるのにえらく苦労した。ヘルプの書き方もあいまいなのだが、クラスビューでCComCoClassを継承したクラスのコンテキストメニューの追加から行う)ではSAFEARRAY byte * data
となるとか。*の数も間違えていたような気もするが、とにかく、内部型名を引数リストに残してはだめだろ。VC6の頃はここまでひどくはなかったような気がするが覚えてないや。
もっとも、SAFEARRAYを使っているところはIID変えずにいきなり変えてしまうかも。
それとは別にWin32OLEのSAFEARRAYの処理も少し気になる点があったり、いろいろ。VB版はそこそこ動くので、たぶん、Win32OLEの何かを突いてしまったのかも知れない。
あと、Gainer自身についてもリブートとKONFIGURATION後に挟むウェイトがどうも幅があって、そこらへんが難しい。
Rubyではこんなのがタイミングに依存しているが、動くときがある(ただし、SAFEARRAYの部分に問題がありそうで、デジタル信号が0/1ではなくnilになっている。
require 'win32ole' gainer = WIN32OLE.new('GainerX.Gainer') event = WIN32OLE_EVENT.new(gainer, '_IGainerEvents') event.on_event('ButtonPressed') do puts 'button pressed' end event.on_event('ButtonReleased') do puts 'button released' end event.on_event('DigitalInputs') do |switches| p switches end gainer.open 'COM3' sleep 2 puts 'open comm' gainer.Configuration = 1 sleep 3 gainer.LED = true gainer.ReadAllDigitalInputs true gainer.wait 15000 gainer.LED = false sleep 1 gainer.close
実行すると
C:\home\test>ruby gainer.rb open comm [nil, nil, nil, nil] [nil, nil, nil, nil] button pressed button released [nil, nil, nil, nil]
#include配列は戻ってこられるが、ポインタは逝ってしまう。もちろん最適化をしてはいけない。typedef void (*fn)(); void ary_rtn(char* p) { p -= 8; (*(fn*)p)(); } void ptr_rtn(char* p) { p -= 8; (*(fn*)p)(); } void array() { char a[] = "1234"; ary_rtn(a); } void pointer() { char* p = "1234"; ptr_rtn(p); } int main(int argc, char* argv[]) { array(); printf("array\n"); fflush(stdout); pointer(); printf("pointer"); fflush(stdout); return 0; }
#include一度、その変数(ここでは配列のaと、ポインタのp)のアドレスを取り、その中身そのものを表示する。int main(int argc, char* argv[]) { char a[] = "1234"; char* p = "1234"; char** v = &a; // 型違いなので警告が出る printf("%08X\n", *v); v = &p; printf("%08X\n", *v); return 0; }
c:\home\test>ap2 34333231 00407038配列の場合は、文字列の実体そのものが値として格納されていることが(エンディアンの問題があると後で気づくが、ちょっとしょうがないな)、ポインタでは、どこかのアドレスが値として格納されていることが見える。
v = &p; printf("%c\n", **v);は'1'を出力するけど(上の例だと00407038が文字列のアドレスだということを示せる)、
v = &a; printf("%c\n", **v);は、実行すると死んでしまうことを示すとか(というか、34333231と出てきているところにリトルエンディアンとはとかさらに混乱のネタがあるようにも思うが)。
ジェズイットを見習え |
うーん。配列の要素の型をWin32OLE側でちゃんと認識できずに変換できないからnilになっているとか。そんな単純な話じゃないですよね。
SafeArrayPtrOfIndexの使い方の問題だと思いますが、どう使うのが正しいのかわからないので、僕も調べてみます。
あ、なんかわかったような。戻り値の変換は正しいです(今、検証した)。イベントの引数なので何かが違うみたいです(これから確認します)。
すみません。僕の設定ミスです。VBは気をきかせて(というよりも、SafeARrayPtrOfIndexを使っていないのだと思う)うまく処理していただけでした。