''[[FrontPage]]''

* visual studioでDLLを作成する [#w92fcb16]

C言語で書いたコードをTclから呼び出すTcl拡張を、visual studioを用いてDLLを作成し、実現します。~
ソースコード中のコメントとプロジェクトのキャプチャを参考に試してみてください。~

** 制約事項 [#ea4fe6e8]
visual studioで開発していくことを前提とする。~
~
~
#ref(http://bj006.com/images/c++_tcl_dll_090502_01.png)
#ref(http://bj006.com/images/c++_tcl_dll_090502_02.png)
#ref(http://bj006.com/images/c++_tcl_dll_090502_03.png)
#ref(http://bj006.com/images/c++_tcl_dll_090502_04.png)
[[おまけ - プリコンパイル済みヘッダを使用する(上):http://bj006.com/images/c++_tcl_dll_090502_05.png]]~
[[おまけ - プリコンパイル済みヘッダを使用する(中):http://bj006.com/images/c++_tcl_dll_090502_06.png]]~
[[おまけ - プリコンパイル済みヘッダを使用する(下):http://bj006.com/images/c++_tcl_dll_090502_07.png]]~

ファイル名:StyleDll.h
 #ifndef         STYLE_DLL                                       //                                                //
 #define         STYLE_DLL                                       //                                                //
                                                                 //                                                //
 #define         USE_TCL_STUBS   1                               //  スタブ機構を使用する                          //
                                                                 //                                                //
 extern "C"                                                      //  C言語としての実装を宣言(必要?)               //
 {                                                               //                                                //
     __declspec( dllexport ) s4 Dlltest_Init( Tcl_Interp* interp ); //  DLL内の関数を外部に公開する                //
 }                                                               //                                                //
                                                                 //                                                //
 #endif                                                          //  STYLE_DLL                                     //
ファイル名:StyleDll.cpp
 #include "X:\XXXXX\XXXXXX\XXXXXXXX\pch.h"                       //  プリコンパイル済ヘッダ                        //
 #include "./StyleDll.h"                                         //  個別ヘッダファイル                            //
                                                                 //                                                //
 /* DLL Test ***************************************************//*  Dllテスト関数                                 */
 static s4 dllTest( ClientData clientData,                       //                                                //
                    Tcl_Interp *interp,                          //                                                //
                    s4 objc,                                     //                                                //
                    Tcl_Obj * CONST objv[] )                     //                                                //
 {                                                               //                                                //
     s4 rntCod = TCL_OK;                                         //  リターンコード                                //
                                                                 //                                                //
     Tcl_AppendResult( interp,                                   //  Tclインタープリタに文字列を返す               //
                       objv[ZERO]->bytes,                        //  コマンド名                                    //
                       " is called. arg1 is ",                   //  編集                                          //
                       objv[ONE]->bytes, NULL );                 //  渡された引数の1番目                          //
                                                                 //                                                //
     return( rntCod );                                           //  正常終了                                      //
 }                                                               //                                                //
 //*DLL Test ***************************************************//*  Dllテスト関数                                 */
 /* Initialize DLL Test ****************************************//*  Dllテスト関数初期化                           */
 s4 Dlltest_Init( Tcl_Interp *interp )                           //                                                //
 {                                                               //                                                //
     s4 rntCod = TCL_OK;                                         //  リターンコード                                //
                                                                 //                                                //
     for( ; ; )                                                  //  無限ループ                                    //
     {                                                           //                                                //
         if( NULL == Tcl_InitStubs( interp, "8.1", ZERO ) )      //  スタブ機構を準備                              //
         {                                                       //  スタブ機構の準備に失敗したら                  //
             rntCod = TCL_ERROR;                                 //  リターンコードに異常を設定                    //
             break;                                              //  処理中断                                      //
         }                                                       //                                                //
                                                                 //                                                //
         Tcl_CreateObjCommand( interp, "Dlltest", dllTest, NULL, NULL ); //  Tcl拡張コマンドを登録                 //
     }                                                           //                                                //
                                                                 //                                                //
     return( rntCod );                                           //  リターンコードを戻して処理終了                //
 }                                                               //                                                //
 //*Initialize DLL Test ****************************************//*  Dllテスト関数初期化                           */
ファイル名:pch.cpp
 #include "X:\XXXXX\XXXXXX\XXXXXXXX\pch.h"                       //  プリコンパイル済みヘッダを指定                //
                                                                 //                                                //
ファイル名:pch.h
 #include        "./comm.h"                                      //  共通ヘッダをプリコンパイル                    //

ファイル名:comm.h
 #ifndef         COMM_H                                          //                                                //
 #define         COMM_H                                          //                                                //
                                                                 //                                                //
 //#pragma comment( lib, "wsock32.lib" )                           //  for socket                                    //
 #pragma comment( lib, "tcl85.lib" )                             //  for C++/TK                                    //
 #pragma comment( lib, "tk85.lib" )                              //  for C++/TK                                    //
                                                                 //                                                //
 #include        <tchar.h>                                       //  for TCHAR etc.                                //
 #include        <tcl.h>                                         //  for TCL                                       //
 //#include        <winsock.h>                                     //                                                //
 #include        <winsock2.h>                                    //  for winsock                                   //
 #include        <windows.h>                                     //  for win32API                                  //
 //#include        <commdlg.h>                                     //  for コモンダイアログ                          //
 #include        <stdio.h>                                       //  標準入出力                                    //
 #include        <fstream>                                       //  ファイルストリーム                            //
 #include        <iostream>                                      //  入出力ストリーム                              //
 #include        <string>                                        //  for string                                    //
 //#include        <vector>                                        //  for vector                                    //
 //#include        <sstream>                                       //  for ostringstream                             //
 #include        <wchar.h>                                       //  for ワイド文字列                              //
 #include        <stdlib.h>                                      //  標準ライブラリ                                //
 //#include        <boost/regex.hpp>                               //  for regex++                                   //
 //#include        <stdarg.h>                                      //  for vararg                                    //
                                                                 //                                                //
 //#using <mscorlib.dll>                                           //                                                //
                                                                 //                                                //
 using namespace std;                                            //  名前空間                                      //
 //using namespace boost;                                          //  名前空間                                      //
                                                                 //                                                //
 //extern HINSTANCE vc_hInst;                                      //  外部変数の宣言                                //
 //extern HWND      vc_hWnd;                                       //  外部変数の宣言                                //
                                                                 //                                                //
                                                                 //  判定用定数定義                                //
 #define         PROC_NG             (-1)                        //  プロセスNG                                    //
 #define         FUNC_NG_NEGATIVE    (-1)                        //  関数NG(-1)                                    //
 #define         FUNC_NG             0                           //  関数NG                                        //
 #define         END_MSG             0                           //  終了メッセージ                                //
 #define         PROCESS_OK          0                           //  処理OK                                        //
 #define         RET_OK              0                           //  リターンOK                                    //
 #define         RET_NG              (-1)                        //  リターンNG                                    //
 #define         WND_HEIGHT          350                         //  ウィンドウ高                                  //
 #define         WND_WIDTH           570                         //  ウィンドウ幅                                  //
 #define         IND_TRUE            1                           //  チェック真                                    //
 #define         IND_FALSE           0                           //  チェック偽                                    //
 #define         ZERO                0                           //  そのまま                                      //
 #define         ONE                 1                           //  そのまま                                      //
 #define         MINUS_ONE           (-1)                        //  そのまま                                      //
 #define         FFFF                65535                       //  そのまま                                      //
 #define         FF                  255                         //  そのまま                                      //
 #define         IND_DUM             (-8)                        //  偽情報の合言葉                                //
                                                                 //                                                //
                                                                 //  共通定数定義                                  //
 #define         MAX_F_NAME          260                         //  ファイル名最大文字数                          //
                                                                 //                                                //
                                                                 //  Window定数定義                                //
 //#define         SCRN_POS_X          50                          //  スクリーンポジションX                         //
 //#define         SCRN_POS_Y          50                          //  スクリーンポジションY                         //
                                                                 //                                                //
 typedef         bool                b0;                         //  変数型別名定義                                //
 typedef         unsigned char       u1;                         //  変数型別名定義                                //
 typedef         signed char         s1;                         //  変数型別名定義                                //
 typedef         unsigned int        u4;                         //  変数型別名定義                                //
 typedef         signed int          s4;                         //  変数型別名定義                                //
 typedef         long                f4;                         //  変数型別名定義                                //
 typedef         double              f8;                         //  変数型別名定義                                //
 typedef         unsigned short      u2;                         //  変数型別名定義                                //
 typedef         signed short        s2;                         //  変数型別名定義                                //
 typedef int Tcl_PackageInitProc( Tcl_Interp *interp );          //  tclインタープリタ                             //
                                                                 //                                                //
 const f8        ROUND_OFF_RATE =    (0.5);                      //  実数型の整数化に使う値                        //
                                                                 //                                                //
 //#include        "./StyleDll.h"                                  //  StyleDllヘッダファイル                        //
                                                                 //                                                //
 //using namespace dNet;                                           //                                                //
                                                                 //                                                //
                                                                 //                                                //
 #endif                                                          //  COMM_H                                        //

ファイル名:PR_dll.tcl
 # HEAD *********************************************************# プログラムに必要な諸々                           #
 package require Tk                                             ;# パッケージの読込み                               #
 #/HEAD *********************************************************# プログラムに必要な諸々                           #
 # Namespace PR_DLL *********************************************# 名前空間(PR_DLL)                                 #
 namespace eval PR_DLL {                                        ;# 名前空間                                         #
 namespace export *                                             ;# すべてのプロシージャを公開                       #
 # Dll Test *****************************************************# DLL使用テスト                                    #
 proc dllTest {} {                                              ;#                                                  #
                                                                ;#                                                  #
 #    .tBar02.r_msg configure -text "platform = $::tcl_platform(platform)" ;# 確認用                                 #
     switch $::tcl_platform(platform) {
         windows {                                              ;# windowsの場合                                    #
             load StyleDll.dll Dlltest                          ;# 作成したdllをロード                              #
 #            load [file join [pwd] StyleDll.dll Dlltest]       ;# この方がいいかも                                 #
             set interp [Dlltest "Hello"]                       ;# 登録したTclコマンドを実行                        #
         }                                                      ;#                                                  #
         unix {                                                 ;# unixの場合                                       #
 #            load [file join [pwd] libfoo[info sharedlibextension]] ;# とりあえずスルー                            #
         }                                                      ;#                                                  #
     }                                                          ;#                                                  #
 #    .tBar02.l_msg configure -text "interp = $interp"           ;# 確認用                                           #
 }                                                              ;#                                                  #
 #/Dll Test *****************************************************# DLL使用テスト                                    #
 }                                                              ;#                                                  #
 #/Namespace PR_DLL *********************************************# 名前空間(PR_DLL)                                 #
 package provide pr_dll 0.01                                    ;# パッケージとバージョンの宣言                     #

*** 修正履歴 [#a1ac3d25]
~

*** 課題 [#e4006fe7]
以下の概念を、管理人自身がいまいち理解してない。~
+Tcl API~
+extern "C"~
~
やりながら覚える。~
ここまで(ロードまで)できればあとはなんとかなる。~

-備考~
初期化関数名に注意が必要です。~
"大文字なんとか_Init" → "load XXXX.dll 大文字なんとか"のカタチじゃなきゃいけないのか?~
Tcl_CreateObjCommandで登録するコマンド名は小文字で始まってもOKです。~
 (TclのdllTestと名前が競合するのを避け、また拡張コマンドであることが明示的にもなるため、"大文字なんとか"に統一しています。)~

*** 参考ページ [#z7cd6fa1]
[[Re: How to build a loadable tcl dll with visual studio (microsoftC compiler)?:http://objectmix.com/c/200303-how-build-loadable-tcl-dll-visual-studio-microsoft-c-compiler-crosspost-comp-lang-tcl-comp-lang-c.html]]~
[[なもなも - 簡単なTclコマンドを作るには:http://www.geocities.co.jp/SiliconValley/4137/dir4/tapi28.html]]

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS