Programming」カテゴリーアーカイブ

プログラミングの話題

Build configuration for TclSQLite with SQLite3MultipleCiphers

Prerequisites

C compiler = gcc version 10.2.0 (Rev6, Built by MSYS2 project)
Tcl build path = /c/src/tcl8.6.11/win
Tcl install path = /c/bin/tcl8.6.11
SQLite3 build path = /c/src/sqlite-autoconf-3340100/tea
SQLite3MultipleCiphers source path = /c/src/wxsqlite3-4.0.4/sqlite3secure/src

Tcl

./configure --prefix=(Tcl install path)
make install

Tk

./configure --prefix=(Tcl install path) --with-tcl=(Tcl build path)
make install

TclSQLite with SQLite3MultipleCiphers

Copy the files in (SQLite3MultipleCiphers source path) to (SQLite3 build path)/generic.
Open tclsqlite3.c and replace "sqlite3.c" by "sqlite3mc.c" in the line #4.

cd (SQLite3 build path)
./configure --enable-threads --prefix=(Tcl install path) --with-tcl=(Tcl build path) CFLAGS="-DCODEC_TYPE=CODEC_TYPE_AES128 -DSQLITE_USE_URI -msse4.2 -maes"
make install

Other notes

I could not make sqlite3 v3.8.2 independent from libgcc_s_dw2-1.dll with MinGW gcc v4.8.1.
I don't know the reason. But I could build it with nmake.
For example:

nmake -f makefile.vc TCLDIR=(Tcl install path) INSTALLDIR=(Tcl install path) OPTDEFINES="-DSQLITE_HAS_CODEC"

References

暗号化APIを有効にしたSQLite3のTclバインディングをコンパイルする

最新Tclkit事情

Tcl/Tkのスクリプトを単体実行ファイルとして配布するのに使うTclkitは、ActiveTclと一緒に配布されるbasekitというのを使っておけば、検証済みの最新バージョンなので問題は少ないのですが、日本語パスやスペースを含むパスから実行しようとするとエラーになるという、何とも前時代的な制約があります。これはフリーソフトとして配布するソフトを作る時にはちょっと受け入れがたいです。そこで、その他のTclkitを手に入れるか、自分でビルドするわけですが。。。ものすごくサイズにこだわりがなければ、今時はKitCreatorのページで出来合いのものを取ってくるのが無難な入手方法です。

手動ビルド版
http://tclkits.rkeene.org/fossil/wiki/Downloads

自動ビルド版(最新版)
http://www.rkeene.org/devel/kitcreator/kitbuild/nightly/

ダウンロードファイルに拡張子.exeをつけます。

ちょっとサイズが大きいので、upxという実行ファイル圧縮ツールを使って小さくするのがお勧めです。

G:\Downloads>upx -k tclkit-8.5.18-win32-i586-threaded-xcompile.exe
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2013
UPX 3.91w       Markus Oberhumer, Laszlo Molnar & John Reiser   Sep 30th 2013
 
        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
   4378912 ->   2759968   63.03%    win32/pe     tclkit-8.5.18-win32-i586-threaded-xcompile.exe
 
Packed 1 file.
 
 
G:\Downloads>ls -l --block-size=KB tclkit-8.5.18-win32-i586-threaded-xcompile.ex*
-rwxrwxrwx  1 yusuke 0 4379kB 2015-06-09 23:31 tclkit-8.5.18-win32-i586-threaded-xcompile.ex~
-rwxrwxrwx  1 yusuke 0 2760kB 2015-06-09 23:31 tclkit-8.5.18-win32-i586-threaded-xcompile.exe

WiresharkにHSMS dissectorを追加したいので参考資料を集める

半導体製造装置とホストとの間の通信にはSEMI Standardで標準化されているHSMS-SS/SECS-IIというプロトコルが使われるのが一般的なのだが、このデバッグツール類はお高いものが多い。Wiresharkにも専用のdissectorはついてないので、自分でプラグインを書くか、サードパーティのdissector pluginを探すしかない。dissectorはDLLまたはLuaスクリプトとして追加できるらしい。

Wireshark Developer’s Guide

How can I add a custom protocol analyzer to wireshark? - StackOverflow

問題児たちがwiresharkのdissectorをLuaで書くそうですよ? - 迷い庭

というか、ここに古いpluginのソースコードが置いてあった。
Bug 8879 - HSMS protocol dissector plugin bug
古くて動作はしないけど、参考にはなりそう。ただ、今はLuaで書いたほうがいいんだろうか。

NativeアプリとManaged DLLの橋渡しをするMixed mode assembly

SQLiteのアカウントデータベースを使って、ユーザー名、パスワードで認証の可否、アカウント情報を取得するようなコンソールアプリを作った。

C++からパイプ経由で呼び出されるのだが、EF使ってたりデータベースのパスワード保護をやってるせいか、接続の初期化に時間がかかって非常に遅かった。

パイプ繋ぎっぱなしというのも考えたけど、使う人が嫌がったので、
ラッパーDLLをリンクしてC++アプリの起動時にだけ接続処理がされるようにしようと思った。
最終的には以下のような構成になった。

accounts.db (SQLite3データベース System.Data.SQLiteの機能で暗号化)
AuthLib.dll (Managed DLL、System.Data.SQLite.dllを使ってデータベースを操作する)
AuthLibHost.exe (Native C++、メインの実行ファイル)
AuthLibHost.exe.config (接続文字列などの情報が書かれた設定ファイル)
AuthLibNative.dll (Mixed mode assembly、AuthLibHostとAuthLibの橋渡し役)
System.Data.SQLite.dll (Mixed mode assembly)

データベースに関するビジネスロジックはAuthLib.dllにすべて実装されているが、
これに対応するラッパー関数をAuthLibNativeにたくさん書くのが面倒だったので、
すべてEvalという一つの関数を経由するようにした。

Evalの引数はコマンドラインインターフェースと類似したargc, argsといったものにして、
加えて出力を格納するための、linesという文字列の配列とその要素数の参照を渡せるようにする。
成功、失敗をEvalの戻り値にする。

ラッパーが不要なC++/CLIを選ぶか、ラッパー書くのが面倒だけど
LINQ to Entitiesとか使えるC#を選ぶかというところですな。

tclkitの仲間

KitCreator Build and Test Status (Nightly build)
最新のバイナリが入手可能。サイズが大きめ。
Windowsの場合はダウンロードしたファイルの拡張子をexeに変える。
http://www.rkeene.org/devel/kitcreator/kitbuild/nightly/

Cookit
Tclkitとはちょっと方式が違うらしい。バイナリはやや古いものしかない。
http://www.endorser.org/en/blog/tcl/cookit/download

Tclkit
バイナリはかなり古く、更新停止中。
https://code.google.com/p/tclkit/wiki/BuildingTclkit

Kitgen build system
自分で作りたい方向け
http://sourceforge.net/projects/kbskit

Tcl8.6系でTDBCをビルトインしてるのがあったらほしいけど今のところ見当たらない。
他にもあった気がするけど思い出したら追記する。

Kitgenで作った小さめのバイナリが手元にあるけど、どこかに置いとこうかな。。。

kitgenをVisual Studio 2012でビルドする

kitgenが正式にサポートしているのはVC6からVC8(2005)までです。
VS2008~VS2013についても、いくつか変更を加えてやればビルドできます。

ただ、これはTclに限ったことではないのですが、VS2012で普通にビルドした実行ファイルはXPで動作しません。SDK 7.1Aにリンクすればビルドできますが、VS2010以前を持ってる人にとっては面倒なだけでメリットがないので古いVSを使った方がいいです。(参考ページ)。

あと、これはいいのかどうか分かりませんが、VC6でビルドするとOS標準添付のC++ランタイム(msvcrt.dll)をリンクするので、別途ランタイムをインストールすることなく動作します。MinGWでビルドした場合もそうなるのでまあ問題ないんじゃないでしょうか。

kitgen/Makefile.vc

70c70
< CFLAGS  = -W3 -D_WINDOWS -DWIN32 -DSTATIC_BUILD
---
> CFLAGS  = -W3 -D_WINDOWS -DWIN32 -DSTATIC_BUILD -D_CRT_SECURE_NO_WARNINGS
142c142,148
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/mk/tcl/mk4tcl.cpp

2597c2597
< EXTERN int Mk4tcl_Init(Tcl_Interp *interp) {
---
> int Mk4tcl_Init(Tcl_Interp *interp) {
2601c2601
< EXTERN int Mk_Init(Tcl_Interp *interp) {
---
> int Mk_Init(Tcl_Interp *interp) {
2605c2605
< EXTERN int Mk4tcl_SafeInit(Tcl_Interp *interp) {
---
> int Mk4tcl_SafeInit(Tcl_Interp *interp) {
2609c2609
< EXTERN int Mk_SafeInit(Tcl_Interp *interp) {
---
> int Mk_SafeInit(Tcl_Interp *interp) {

kitgen/8.x/mk/tcl/mk4tcl.h

382a383,391
> 
> 
> EXTERN int Mk4tcl_Init(Tcl_Interp *interp);
> 
> EXTERN int Mk_Init(Tcl_Interp *interp);
> 
> EXTERN int Mk4tcl_SafeInit(Tcl_Interp *interp);
> 
> EXTERN int Mk_SafeInit(Tcl_Interp *interp);

kitgen/8.x/itcl/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/mk/win/rules.vc

187c187,195
< !if $(VCVERSION) >= 1400
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500
> VCVER=9
> !elseif $(VCVERSION) >= 1400
189,190d196
< _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
< _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
195a202,205
> !if $(VCVERSION) >= 1400
> _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
> _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
> !endif

kitgen/8.x/thread/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

kitgen/8.x/vqtcl/win/rules.vc

195c195,201
< !if $(VCVERSION) >= 1500
---
> !if $(VCVERSION) >= 1800
> VCVER=12
> !elseif $(VCVERSION) >= 1700
> VCVER=11
> !elseif $(VCVERSION) >= 1600
> VCVER=10
> !elseif $(VCVERSION) >= 1500

8.6.1をビルドするには、kitgen、Tcl、Tkのソースをダウンロードして、
以下にコピーします。

C:\src\kitgen
C:\src\kitgen\8.6.1\tcl
C:\src\kitgen\8.6.1\tk

Visual Studioのコマンドプロンプトを開き、

mkdir C:\src\kitgen\8.6.1\kit-msvc
cd C:\src\kitgen\8.6.1\kit-msvc
echo all: lite heavy > Makefile
echo !include ..\..\Makefile.vc >> Makefile
nmake -f Makefile.vc -nologo VERSION=86 KITOPTS=”-t -z”

ちなみに、tdbc関連のモジュールが大量にビルド失敗しますが、使わない限りは問題ありませんでした。

kitgen+VC6でtclkitを作るときの注意点

TclAppを使うと、Tcl/Tkのスクリプトと実行環境を単一のEXEファイルにラップすることができるのですが、このときprefixファイルといって、ベースとなる実行ファイルを指定する必要があります。これをtclkitとかbasekitとか呼び、標準ライブラリや最低限のエンコーディングファイルなどが含まれていて、自分で開発したアプリに必要な、スクリプト一式、ライブラリ、エンコーディングなどを、TclAppを使って追加することで単体のアプリとして動作するようになります。アイコンやバージョン情報なども、prefixに組み込まれているものを置き換えることもできます。

prefixとして使えるファイルは、実はActiveTclにbasekitという名前でついてきます(Tcl/binフォルダにある)。これがあれば別に自分でtclkitを入手する必要はないのですが、2点ほど問題があります。

  • 実行ファイルのサイズが比較的大きい
  • バイトコードコンパイルすると、スペースおよびマルチバイト文字を含むパスから起動できない

ということで、私にとっては不都合だったので、basekitをやめてtclkitを使うことにしました。tclkitのWindowsバイナリはTcl8.5.13まではhttp://www.patthoyts.tk/tclkitで配布していたのですが、8.5.14がなかなか出ないなあと思っていたら今日見たら落ちてました。また、配布しているものにはtzdataというタイムゾーンの定義ファイルがないので、時刻表示が狂う場合がありました。そういう理由があって、自分でコンパイルすることにしました。前置きが長くなりましたが、以下がその手順です。Windows7 Professional SP1 32bit上で試しました。

必要なものをそろえる

Visual Studio 6.0 (Visual Studio 2003でもいいと書いてあった。)
Microsoft Platform SDK Febuary 2003 (Last version with VC6 support)

kitgenのソースコードを取ってくる

C:\src\kitgenに展開。

Tcl/Tkのソースコードを取ってくる

C:\src\kitgen\8.5\tcl
C:\src\kitgen\8.5\tkに展開。

ビルド用のフォルダとMakefileを作る

VC6のコマンドプロンプトを開く
mkdir C:\src\kitgen\8.5\kit-msvc
cd C:\src\kitgen\8.5\kit-msvc
echo all: lite heavy > Makefile
echo !include ..\..\Makefile.vc >> Makefile

リソースファイルを編集する

これはお好みですが、kitgenに添付されているものを使うと、TclAppでバージョン情報を編集できなくなるので、変更することをお勧めします。
C:\src\kitgen\tclkit.rcをテキストエディタで開き、CommentとPaddingを削除する。

            VALUE "Comments", "Comments\0More Comments\0"
            VALUE "Padding",
               "                                                            "
               "                                                            "
               "                                                            "
               "                                                            \0"

ビルドする

Platform SDKを参照するようにします。また、KITOPTS=-zというオプションを与えることで、tzdataが含まれるようにします。他にもオプションがありますが、kitgenのREADMEファイルを読んでください。

set INCLUDE=C:\PROGRA~1\MIC1C5~1\include;%INCLUDE%
nmake -f Makefile.vc -nologo VERSION=85 KITOPTS="-z"

C:\src\kitgen\8.5\kit-msvcの中にできる、tclkit-cli.exe、tclkit-gui.exeをTclAppのprefixに指定できます。

UI Automation Clients

UI Automationについて参考になりそうなページを50個ほどブックマークしたものの、多すぎるので入口として役立ちそうなページを抜粋しておく。
本来はUIテストやアクセシビリティを目的としているようだが、今回は他人が作ったソフトを自動制御するために使う。
プロバイダとクライアントの説明があるが、今回はクライアントのことが分かればよいはず。
Windows Forms、WPF、サードパーティのUIコンポーネントでもたいていはオートメーションプロバイダとして扱えるようだ。
確証はないがUISpy.exeを使ってAutomationIdなどが確認できれば対応していると思っていいのではないかと思っている。

UI Automation のススメ

UI Automation Fundamentals

UI Automation Client Programmer's Guide (Windows)

Use the AutomationID Property

Bugslayer - こちらGUIコントロール、トム少佐応答せよ

UIツリーを辿り、プロパティを確認するにはUISpyやInspect Objectというのがある。
UI Spy(UISpy.exe)が含まれているWindows SDK Version

現状はC#でやるのが無難そうだ。
TclでもGarudaを使うと、インプロセスで.NET Frameworkのクラスを利用できるのだが、まだ未完成、ドキュメントがないに等しいので難しい。クラスメソッドやイテレーションを使えるのかすら分からない。
COMは茨の道だと思われるのでできれば避けたい。

ちまちまUI Treeを歩き回るコードを書く代わりに、もっと楽にしてくれるライブラリというのもあるみたいだ。
White
White Tutorial
StackOverflow White - File Open Dialog Box
White - Working with window

UISpyみたいなインターフェースと、UI Automationプロバイダとして必要な機能を持っているかチェックするためのソフト。
Visual UI Automation Verify
UIVerifyが内部で使っているライブラリがこれ。
UI Automation COM-to-.NET Adapter
.NET版のAPIがあるのに何でラッパーを作る必要があるのかは気になるが、まだ調べてない。

Tclでベクトル計算するサンプル

SXGAのリモートデスクトップウィンドウをアスペクト比を保ちつつ65%に縮小し、FullHDのディスプレイの右下に配置したい。手計算でも簡単にできることだが、今まで使ってなかった行列計算ライブラリの練習台に使うことを思いついた。

+-----------------------------+
|                             |
|                             |
|                             |
|                             |
|                             |
|               nw------------+
|               |xxxx         |
|               |   x rec x   |
|               |        xxxx |
|               |           xxx
+---------------+------------se
package require math::linearalgebra
namespace eval LinearAlgebraSample {
  namespace import -force ::math::linearalgebra::*
 
  set scale 0.65
  set v(se) [mkVector 2]
  set v(rec) [mkVector 2]
 
  setelem v(se) 0 0 1920
  setelem v(se) 1 0 1280
 
  setelem v(rec) 0 0 1280
  setelem v(rec) 1 0 1024
 
  set v(nw) [sub_vect $v(se) [scale $scale $v(rec)]]
  show $v(nw)
}

例題がしょぼすぎて練習になってないな。

線形代数苦手でプログラミングにも活用してないし、Maxima、Scilab、Octave、Rとかも使ってない。
ロボットの研究室にいたのに行列計算が苦手というのは勉強してなかった証拠ですね。