制作中の VBAEnumration の話
For Each で列挙できるようにするため、EnumVariat をVBAから CoTaskMemAlloc() でメモリ確保して作っています。
そこに標準モジュール関数を登録した vtable をセットして仮想関数持ちのオブジェクトを再現しているんですが、なんか AddRef() で時々落ちてしまいます。エクセルが。
dim a as IEnumVariant
set a = q.NewEnum
だと落ちないっぽいのに、
dim a as variant
set a = q.NewEnum
だと、set a = したところで addref() に飛んで、そこを抜けると落ちる。気がする。
原因がわかんないなぁー
こういう悩み中みたいな話を GitHub のどこかにのせていってもいいんだろうか
Readme とか Issue?は違うのかな目的が
2017年10月31日火曜日
2017年10月25日水曜日
VBAでLINQみたいなことができるクラス群
意味ないものですが作成中
https://github.com/abarabone/vbaEnumeration
GitHub にアップしてるんだけど Git も GitHub もよくわかりませぬ…
とりあえず一通りのオペレータができるまでは黙々とやっていきます
実用性はないでしょうけど
https://github.com/abarabone/vbaEnumeration
GitHub にアップしてるんだけど Git も GitHub もよくわかりませぬ…
とりあえず一通りのオペレータができるまでは黙々とやっていきます
実用性はないでしょうけど
2017年7月5日水曜日
クソVBAをやってる話
VBAでラムダのようなものを使いたくて試行錯誤中
まずは引数として渡せる関数の再現
試行錯誤の履歴
・Application.Run() … 名前文字列で指定する 重め
参照引数が使えない
Application ってどうなの
・CallByName() … 名前文字列で指定する 重め
参照引数は使える
オブジェクトのメソッドしか呼べない
・イベント … 汎用的に呼べるイベントを作ってやることで再現 軽め!
戻り値はない エラーを呼び出し元に Raise できない
withEvents のメンバにセットした値を外部に持ち出せば、
対応したイベントを呼び出すことができる
イベントに光を見出して、文字列コードをラムダにして動的モジュールを生成していくようにした。
LINQのオペレータ的なものを、Skip, Take, Select, Where, SelectMany, くらいまで作成した。
しかし for each に対応させられずに、Do Loop で回す感じになっていて、不満があった。
IEnumVariant を V-table ごとメモリ上に構築してしまえばよいことを知る。
APIを使用することをなぜか拒んでいたが、解禁する。つまらないこだわりだったと思う。
VBAのオブジェクトはCOM関係そのものということに気づく。
で、ついでにここでこれに気づいてしまう…
・DispCallFunc() … AddressOf で関数ポインタを得て、使用できる。
参照引数も使用できる。型も使用できる。
が、引数指定のクセが強く、たやすくハングアップする。これは問題。
なやむ。
また、オブジェクトのメソッドを V-table のオフセットで指定実行できる。
そこからVBAのクラスは IDispatch を継承しているということに気づく。
ITypeInfo を作成すればいろいろいじれる。
ただ、本当に DispCallFunc() の引数はセンシティブで、試行錯誤しまくった。情報もないし…。
また、クラスメソッドを呼ぼうとしたときに、第一引数が戻り値になってしまうという謎の現象に遭遇。
回避できない。
同じことで悩んでる外人さんもいた。
どうしたものか
そこで今、このページを発見。
https://msdn.microsoft.com/en-us/library/ms221141(v=vs.85).aspx
うおぅ!!
今までやってた煩雑なことが、APIでできそう???
と興奮すると同時に徒労感が。
いまここ。
まずは引数として渡せる関数の再現
試行錯誤の履歴
・Application.Run() … 名前文字列で指定する 重め
参照引数が使えない
Application ってどうなの
・CallByName() … 名前文字列で指定する 重め
参照引数は使える
オブジェクトのメソッドしか呼べない
・イベント … 汎用的に呼べるイベントを作ってやることで再現 軽め!
戻り値はない エラーを呼び出し元に Raise できない
withEvents のメンバにセットした値を外部に持ち出せば、
対応したイベントを呼び出すことができる
イベントに光を見出して、文字列コードをラムダにして動的モジュールを生成していくようにした。
LINQのオペレータ的なものを、Skip, Take, Select, Where, SelectMany, くらいまで作成した。
しかし for each に対応させられずに、Do Loop で回す感じになっていて、不満があった。
IEnumVariant を V-table ごとメモリ上に構築してしまえばよいことを知る。
APIを使用することをなぜか拒んでいたが、解禁する。つまらないこだわりだったと思う。
VBAのオブジェクトはCOM関係そのものということに気づく。
で、ついでにここでこれに気づいてしまう…
・DispCallFunc() … AddressOf で関数ポインタを得て、使用できる。
参照引数も使用できる。型も使用できる。
が、引数指定のクセが強く、たやすくハングアップする。これは問題。
なやむ。
また、オブジェクトのメソッドを V-table のオフセットで指定実行できる。
そこからVBAのクラスは IDispatch を継承しているということに気づく。
ITypeInfo を作成すればいろいろいじれる。
ただ、本当に DispCallFunc() の引数はセンシティブで、試行錯誤しまくった。情報もないし…。
また、クラスメソッドを呼ぼうとしたときに、第一引数が戻り値になってしまうという謎の現象に遭遇。
回避できない。
同じことで悩んでる外人さんもいた。
どうしたものか
そこで今、このページを発見。
https://msdn.microsoft.com/en-us/library/ms221141(v=vs.85).aspx
うおぅ!!
今までやってた煩雑なことが、APIでできそう???
と興奮すると同時に徒労感が。
いまここ。
2017年6月4日日曜日
async/await について
async/await
await XxxxAsync();
と記述した時、XxxxAsync() が終了するまで制御をOSに返し、
それ以降の実行を待機する仕組み
async 関数を await で実行
void を返す ... fire & forget
Task<int> を返す ... 非同期処理完了後に同期して int を返す
Task を返す ... 非同期処理完了後に同期して void を返す
fire & forget とは
await XxxxAsync(); と、その下に続くコードが並列実行される
(ノンブロッキング関数的なイメージ)
await
await XxxxAsync(); の下に続くコードは、
XxxxAsync() から戻ってきた後に実行されるコールバックとしてコンパイルされる。
コールバックが実行されるスレッドを決定するのが同期コンテキスト。
同期コンテキスト(synchronization context)
Task オブジェクトがタスク実行後に戻る文脈を保持する。
await 呼び出し側の SynchronizationContext.Current に戻ってくるように設定される。
デフォルトでは task.ConfigureAwait( true ) となっており、同期コンテキストが適用される。
実行環境による同期コンテキストの違い
WPF等GUI … UIスレッド
ASP.NET … リクエストとレスポンスが同一スレッド
コンソール … null(同期コンテキストが存在しない)
※同期コンテキストが存在しない
= 戻るべきスレッドを規定しない
= スレッドプールの任意のスレッドに戻る(というか移行)
同期コンテキストを無視したいとき
await XxxAsync().ConfigureAwait( false );
コンソールと同じ動作となる
単に、何かの処理を別スレッドで実行したい場合について
await/async で、せっかくコールバックをインデントのネストから解放できたのに、
任意の処理を別スレッドでさせたいときなんかに Task.Run() で処理を書かざるを得ないのはダサく感じる。
平坦に書きたいです。
平坦に書きたいです。
同期コンテキストがなければ await Task.Yield() でそれ以降を別スレッドに移せるぽいが、
そうでない場合は await Task.Run( () => {} ).ConfigureAwait( false ); などと書かないとダメかも。
でも無意味なタスクオブジェクトが発生したりしそう。
そもそも、async/await は非同期タスクを待ち受けるための構文であって、
スレッド実行を平坦に記述するという汎用的な目的で使うべきものではない、ということか。
同期させるスレッドを自由に切り替えできればいいのにと思うけど、そういう思想のものじゃない、のか…。
そもそも、async/await は非同期タスクを待ち受けるための構文であって、
スレッド実行を平坦に記述するという汎用的な目的で使うべきものではない、ということか。
同期させるスレッドを自由に切り替えできればいいのにと思うけど、そういう思想のものじゃない、のか…。
登録:
投稿 (Atom)
ニューラルネットやってみてる
最近ニューラルネットやってみてる 理屈を学ぼうと思って、まずはオブジェクト的に作ってみてる (ベクトル化とかは後回しで) sigmoid, tanh, ReLU MSE, cross entorpy あたりを小規模にいじってみてます でも今 soft max の逆伝...
-
VBAでラムダのようなものを使いたくて試行錯誤中 まずは引数として渡せる関数の再現 試行錯誤の履歴 ・Application.Run() … 名前文字列で指定する 重め 参照引数が使えない Appli...
-
Unity ECS をやっています 現状を書きなぐります すみませんが推敲しません ところで「Unity ECS 完全に理解した」という勉強会に行きたかったのだけど、いけなかった。 キャンセルをぎりぎりまでやきもきしながら見守ったのだけども、地方からの移動時間を考えてあき...
-
variant 型に IEnumVariant をセットしようとしたときにエクセルが落ちることがある件の続き。 いろいろ試してみると、set variant = a.NewEnum() の時 queryInterface() でGUID B196B283-BAB4-101A-B...