わたなべです.

Katsuyuki Komatsu <komatsu / sarion.co.jp> writes:

:そういえば、rbcw145.zipで、
:    tcltklib76.dll
:    tcltklib81.dll
:    tcltklib82.dll
:    tcltklib83.dll
:とあるのに、setupで標準で入るtcl8.0用がないのはなぜですか?

これらは全部 Windows 用の Tcl/Tk で Cygwin 用のではないです.
8.0 がないのは単に入手してないからというだけで.
で, cyg{tcl,tk}80.dll 用がなぜないかというと, なぜだろう?
言われるまで気づきませんでした. やっぱ混乱するからかな.
最初に B19 あたりについてきたのがバグっててまったく動かな
かったというのがトラウマになっているのかも.

で 1.5.4 のほうは馬鹿らしくなって 8.3 用しか作ってません.

今は環境変数 TCL_LIBRARY から load すべき DLL 名を判断し
LoadLibraryEx して必要な symbol を GetProcAddress して
jmp するだけの stub で対応しようかななんて思ってます.

__asm あたりが gcc 依存ですけど, こんな感じで.
-- 
わたなべひろふみ

#!/usr/local/bin/ruby require 'rbconfig' nm = Config::CONFIG["NM"] symbols = [] for line in `#{nm} tcltklib.o` if / U _(T\w+)/ === line symbols << $1 end end open("ttproxy.c", "w") do |tt| tt.print <<EOM #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> EOM for sym in symbols tt.print "static void (*p#{sym})();\n" end tt.print <<'EOM' WINAPI dll_entry(int a, int b, int c) { static HINSTANCE h_tcl, h_tk; char *tcl; char *tk; switch (b) { case DLL_PROCESS_ATTACH: tcl = getenv("RUBY_TCL_DLL"); tk = getenv("RUBY_TK_DLL"); if (tcl && tk) ; else if (tcl = getenv("TCL_LIBRARY")) { char *p; if (p = strrchr(tcl, '\\')) tcl = p; else if (p = strrchr(tcl, '/')) tcl = p; if (tcl[5] == '.') { static char tcl_template[] = "tclxx"; static char tk_template[] = "tkxx"; tcl_template[3] = tcl[4]; tcl_template[4] = tcl[6]; if (tcl[3] == '7') { tk_template[2] = '4'; tk_template[3] = '2'; } else { tk_template[2] = tcl[4]; tk_template[3] = tcl[6]; } tcl = tcl_template; tk = tk_template; } else { printf("set TCL_LIBRARY\n"); return 0; } } else { printf("set TCL_LIBRARY\n"); return 0; } h_tcl = LoadLibraryExA(tcl, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (!h_tcl) { printf("cannot find %s\n", tcl); return 0; } h_tk = LoadLibraryExA(tk, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (!h_tk) { printf("cannot find %s\n", tk); return 0; } EOM for sym in symbols if /Tcl/ === sym name = "tcl" else name = "tk" end tt.print "\tp#{sym} = (void (*)())GetProcAddress(h_#{name}, \"#{sym}\");\n" end tt.print <<'EOM' break; case DLL_PROCESS_DETACH: FreeLibrary(h_tcl); FreeLibrary(h_tk); break; default: } return 1; } EOM for sym in symbols tt.print <<EOM __asm (".text;.global _#{sym};.def _#{sym};.scl 2;.type 32; .endef;_#{sym}: jmp *_p#{sym}"); EOM end end