C#からTcl/Tkを使おうとして苦戦中
高木です。おはようございます。
私が以前からTcl/Tkをよく使っていることは、このブログを丹念に読まれている方ならご存知かと思います。
今回も、とある製品にTcl/Tkを組み込む可能性について、事前に調査を行っています。
当然のことながら具体的なことはここでは書けないのですが、当たり障りのないことだけは共有していきたいと考えています。
今回の構想では、C#からTcl/Tkを使おうとしています。
といっても、TclやTkのDLLをDllImportを使ってC#から直接呼び出そうとは考えていません。
いったんC++/CLIを介して、C#(というか.NET言語)からTcl/Tkの機能を使えればと考えています。
とりあえず、最新バージョンであるTcl/Tk 8.6.8のソースを入手しました。
最初は安易に、nmakeを使ってwin/Makefile.vcを実行すればビルドできるだろうと考えていました。
実際、Tclはすぐにビルドできました。
しかし、Tkで問題に直面します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Microsoft(R) Program Maintenance Utility Version 14.13.26131.1 Copyright (C) Microsoft Corporation. All rights reserved. *** Using W:\work\tcl8.6.8\win\rules.vc *** Using W:\work\tcl8.6.8\win\nmakehlp.c *** Compiler has 'Optimizations' *** Building against Tcl at 'W:\work\tcl8.6.8' *** Intermediate directory will be 'W:\work\tk8.6.8\win\Release_AMD64_VC1913\tk_ThreadedDynamic' *** Output directory will be 'W:\work\tk8.6.8\win\Release_AMD64_VC1913' *** Installation, if selected, will be in 'C:\Tcl' *** Suffix for binaries will be 't' *** Compiler version 1913. Target machine is AMD64 *** Host architecture is AMD64 TCLINSTALL=0 *** Dependency rules are not being used. cl -nologo -c /D_ATL_XP_TARGETING /DUNICODE /D_UNICODE -W3 -wd4311 -wd4312 -FpW:\work\tk8.6.8\win\Release_AMD64_VC1913\tk_ThreadedDynamic\ -fp:strict -O2 -GS -GL -MD -I"W:\work\tcl8.6.8\generic" -I"W:\work\tcl8.6.8\win" -I"W:\work\tk8.6.8\win\..\win" -I"W:\work\tk8.6.8\win\..\generic" -I"W:\work\tk8.6.8\win\..\bitmaps" -I"W:\work\tk8.6.8\win\..\xlib" -DBUILD_ttk -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DSUPPORT_CONFIG_EMBEDDED -DHAVE_UXTHEME_H=1 -Dinline=__inline -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE -DTCL_CFGVAL_ENCODING=\"cp1252\" -DSTDC_HEADERS -DTCL_THREADS=1 -DUSE_THREAD_ALLOC=1 -DNDEBUG -DTCL_CFG_OPTIMIZED -DTCL_CFG_DO64BIT -DTCL_USE_STATIC_PACKAGES=0 -FoW:\work\tk8.6.8\win\Release_AMD64_VC1913\tk_ThreadedDynamic\winMain.obj W:\work\tk8.6.8\win\..\win\winMain.c winMain.c C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20062): error C2059: 構文エラー: '定数' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20074): error C2059: 構文エラー: '}' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20075): error C2059: 構文エラー: '}' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20076): error C2143: 構文エラー: '{' が '*' の前 にありません。 C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20084): error C2061: 構文エラー: 識別子 'IMAGE_POLICY_ENTRY' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20085): error C2059: 構文エラー: '}' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\winnt.h(20086): error C2143: 構文エラー: '{' が '*' の前 にありません。 C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\processthreadsapi.h(1126): error C2059: 構文エラー: '定数' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\processthreadsapi.h(1128): error C2059: 構文エラー: '}' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\processthreadsapi.h(1250): error C2059: 構文エラー: '定数' C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um\processthreadsapi.h(1252): error C2059: 構文エラー: '}' NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.13.26128\bin\HostX64\x64\cl.EXE"' : リターン コード '0x2' Stop. |
ざっと試した感じでは、上記のようなエラーが出てしまうのです。
直接の原因としては、Noneという名前のマクロが衝突していることにあります。
ただ、#undef Noneを挿入しても、今度はControlMaskが衝突しています。
また、単にNoneの定義を#undefで解除しただけでは、今度はNoneが未定義だということでエラーが出ることもあります。
要するに、なかなか一筋縄ではいきません。
そもそもソースからビルドしたかった理由は、アプリケーションから参照する(Visual C++の)ランタイムライブラリをひとつに絞りたかったということがあります。
複数のランタイムライブラリが混在していると、それはそれで嫌な問題が起きるからです。
しかし、C#から呼び出すことを想定している時点で、そこにはあまりこだわらなくてもいいのかもしれません。
それであれば、少しバージョンは古くなりますがActiveTclを使ってもいいでしょうし、MinGW-w64でビルドしてもかまわないでしょう。
何でもいいので、C++/CLIからTcl/Tkを呼び出すことさえできればしめたものです。
あとは既知の技術ですべてカバーできそうです。
もうひとつの選択肢としては、プロセスを分けてしまうという方法もあります。
ただ、それだとアプリケーションで使いたい特殊なコマンドを、プロセス間通信を使ってかなり回りくどいことをしないと呼び出せなくなります。
これは避けたいところです。
この件に関しては、今後も必要になってきそうですので追跡調査を行いたいと思います。
今回はとりあえず「うまくいかなかった」報告だけになりますが、いずれ続報をお伝えしたいと思います。