4

dll をコンパイルしてロードするために多くの Web オプションを試して検索した後、tcl 用の dll を作成できませんでした。これを行う方法を説明してもらえますか。

4

1 に答える 1

8

わかりました、ここに簡単な例があります。このコードは、Tcl8.5 および VS2008 でコンパイルおよび動作します。まず、シンボルをエクスポートする BasicTclExtn という名前の WIN32 dll プロジェクトを作成しました。

// BasicTclExtn.h
#ifdef BASICTCLEXTN_EXPORTS
#define BASICTCLEXTN_API __declspec(dllexport)
#else
#define BASICTCLEXTN_API __declspec(dllimport)
#endif

int BasicExtnCmd(ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) ;
extern "C" {
    BASICTCLEXTN_API int Basictclextn_Init(Tcl_Interp *interp) ;
}

そして、.cpp ファイル

// BasicTclExtn.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
#include "BasicTclExtn.h"

int
BasicExtnCmd(ClientData data,
             Tcl_Interp *interp,
             int objc,
             Tcl_Obj *CONST objv[])
{

    // Check the number of arguments
    if (objc != 3) {
        Tcl_WrongNumArgs(interp, 1, objv, "arg arg");
        return TCL_ERROR;
    }

    long v1, v2, result ;

    if ( Tcl_GetLongFromObj(interp, objv[1], &v1) != TCL_OK)
        return TCL_ERROR ;

    if ( Tcl_GetLongFromObj(interp, objv[2], &v2)  != TCL_OK)
        return TCL_ERROR ;

    result = v1 + v2 ;

    Tcl_SetObjResult(interp, Tcl_NewIntObj(result)) ;
        return TCL_OK ;
}

    // Note the casing on the _Init function name
    BASICTCLEXTN_API int Basictclextn_Init(Tcl_Interp *interp)
    {
        // Link with the stubs library to make the extension as portable as possible
        if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
            return TCL_ERROR;
        }

        // Declare which package and version is provided by this C code
        if ( Tcl_PkgProvide(interp, "BasicTclExtn", "1.0") != TCL_OK ) {
            return TCL_ERROR ;
        }

        // Create a command
        Tcl_CreateObjCommand(interp, "BasicExtnCmd", BasicExtnCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);

        return TCL_OK ;
    }

stdafx.h に tcl.h を #include する必要があります。

この例では、Tcl スタブ機能を使用しています。詳細については、Tcl_InitStubs 関数のドキュメントを参照してください。スタブを使用する場合は、tclstub85.lib のみにリンクする必要があります。コードを適切にリンクするには、次の手順を実行する必要があります。

  • tcl.h がインストールされているインクルード ディレクトリを [構成プロパティ] -> [C/C++] -> [全般] -> [追加のインクルード ディレクトリ] に追加します。
  • シンボルを定義しUSE_TCL_STUBSます。私は通常、Properties-> C/C++ -> Preprocessor -> Preprocessor Definitions でこれを行います。<DLLNAME>_EXPORTSこの後、 (BASICTCLEXTN_EXPORTS私の例では)を定義する必要があることに気付くかもしれませんが、なぜこれが起こるのかわかりません。
  • [構成プロパティ] -> [リンカー] -> [一般] -> [追加のライブラリ ディレクトリ] で、tclstub85.lib ファイルがあるディレクトリへのパスを追加のライブラリ ディレクトリとして追加します。
  • 構成プロパティに tclstub85.lib を追加 -> リンカー -> 入力 -> 追加の依存関係
  • コンパイラが MSVCRT に関する警告を吐き出す場合は、[構成プロパティ] -> [リンカー] -> [入力] -> [特定のライブラリを無視] で無視されたライブラリに追加して、MSVCRT を除外します。

これらの .lib、.dll、および .h ファイルはすべて、Tcl インストールで簡単に見つけることができます。また、関連する tclstub85.dll と tcl85.dll が実行時に見つかることを確認する必要があります。Tcl の bin ディレクトリが PATH にあることを確認して、それを整理する必要があります。したがって、Tcl から次のことができるはずです。

C:\Projects\BasicTclExtn\Debug>tclsh
% load BasicTclExtn.dll
% BasicExtnCmd 1 2
3
% BasicExtnCmd 1 2.p
expected integer but got "2.p"
% BasicExtnCmd 1 2
3
% BasicExtnCmd 1
wrong # args: should be "BasicExtnCmd arg arg"
% BasicExtnCmd 1 3
4
% exit

これは Tcl 拡張機能の最も単純な形式です。追加の呼び出しをTcl_CreateObjCommand()追加して、この拡張機能にさらにコマンドを追加できます。Tcl は、コマンドに渡されるコマンド ライン パラメータの処理を支援するいくつかの機能を提供します。サンプルコードが使用されTcl_WrongNumArgs()ていますが、Tcl_GetIndexFromObj()関数も確認する必要があります。

また、Brent Welch による Tcl および Tk での実用的なプログラミングのコピーを入手することをお勧めします。ここでいくつかのサンプルの章を読むことができますhttp://www.beedub.com/book/、第3版のTclのCプログラミングに関する章は大いに役立ちます。

于 2009-09-08T09:19:11.027 に答える