dll をコンパイルしてロードするために多くの Web オプションを試して検索した後、tcl 用の dll を作成できませんでした。これを行う方法を説明してもらえますか。
1 に答える
わかりました、ここに簡単な例があります。このコードは、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プログラミングに関する章は大いに役立ちます。