我正在按照this指南在C中编写一个简单的Tcl扩展。我已经在文章中提供了源代码,并且我正在使用MSVC的命令行编译器编译(cl.exe )。我的目标是将此源代码转换为共享库(DLL)并允许我的Tcl脚本访问此共享库以使用我实现的Tcl扩展。
我在以下目录中安装了Tcl:
C:\Tcl
以下是源代码:
TclExample.h
#include <tcl.h>
/* <package_name>_Init is called when a package is loaded. In this case,
since our package is named "Random", we call the function Random_Init()
*/
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) int Random_Init(Tcl_Interp* interp);
//EXTERN int Random_Init(Tcl_Interp* interp);
__declspec(dllexport) int RandomCmd(ClientData cd, Tcl_Interp* interp, int argc, char* CONST argv[]);
//EXTERN int RandomCmd(ClientData cd, Tcl_Interp* interp, int argc, char* CONST argv[]);
__declspec(dllexport) int RandomObjCmd(ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj *CONST objv[]);
//EXTERN int RandomObjCmd(ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
#ifdef __cplusplus
}
#endif
TclExample.c
#include "TclExample.h"
/* <package_name>_Init is called when a package is loaded. In this case,
since our package is named "Random", we call the function Random_Init()
*/
int Random_Init(Tcl_Interp* interp)
{
/* Initialize the stub table interface */
if (Tcl_InitStubs(interp, "8.1", 0) == NULL){
return TCL_ERROR;
}
/* Create two varations of the "random" procedure.
The orandom command uses the object interface
*/
Tcl_CreateCommand(interp, "random", RandomCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "orandom", RandomObjCmd, NULL, NULL);
/* Declare that we implement the random package so scripts that do "package require random"
load the library right away
*/
Tcl_PkgProvide(interp, "random", "1.0");
return TCL_OK;
}
/* Defined procedures implementation */
int RandomCmd(ClientData cd, Tcl_Interp* interp, int argc, char* CONST argv[])
{
int rand = 0, error = 0, range = 0;
if (argc > 2){
interp->result = "Incorrect number of args. Usage: random ?range?";
return TCL_ERROR;
}
if (argc == 2){
if (Tcl_GetInt(interp, argv[1], &range) != TCL_OK){
return TCL_ERROR;
}
}
//rand = random();
if (range != 0){
rand %= range;
}
sprintf(interp->result, "%d", rand);
return TCL_OK;
}
int RandomObjCmd(ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj *CONST objv[])
{
int rand = 0, error = 0, range = 0;
if (objc > 2){
Tcl_WrongNumArgs(interp, 1, objv, "?range?");
return TCL_ERROR;
}
if (objc == 2){
if (Tcl_GetIntFromObj(interp, objv[1], &range) != TCL_OK){
return TCL_ERROR;
}
}
//rand = random();
if (range != 0){
rand %= range;
}
Tcl_Obj* resultPtr = Tcl_GetObjResult(interp);
Tcl_SetIntObj(resultPtr, rand);
return TCL_OK;
}
以下是我在MSVC命令行中使用的命令:
cl /I C:\Tcl\include\tcl8.5 /DUSE_TCL_STUBS /DBUILD_tcl /Ox TclExample.c
/link /DLL /LIBPATH C:\Tcl\lib\tclstub85.lib /LIBPATH C:\Tcl\lib\tkstub85.lib
/LIBPATH C:\Tcl\lib\ttkstub.lib /OUT:TclExample.dll
如您所见,我已将include
路径包含在C:\Tcl\include\tcl8.5
中的Tcl标头中,并包含位于C:\Tcl\lib
中的存根库。
运行上述命令时出现以下错误:
/out:TclExample.exe
/DLL
/LIBPATH
C:\Tcl\lib\tclstub85.lib
/LIBPATH
C:\Tcl\lib\tkstub85.lib
/LIBPATH
C:\Tcl\lib\ttkstub.lib
/OUT:TclExample.dll
TclExample.obj
Creating library TclExample.lib and object TclExample.exp
TclExample.obj : error LNK2019: unresolved external symbol _Tcl_InitStubs referenced in function _Random_Init
TclExample.obj : error LNK2019: unresolved external symbol _tclStubsPtr referenced in function _Random_Init
TclExample.dll : fatal error LNK1120: 2 unresolved externals
我尝试过在线挖掘,但是我已经陷入困境了。我查看了Tcl.h
标题,我确实看到了那里声明的Tcl_InitStubs函数。此外,我不知道tclStubsPtr错误来自何处,因为我在源代码中没有使用该名称的函数。有谁知道这里的问题是什么?
另外,我现在仅限于使用命令行,所以我需要一个命令行解决方案(如果可能的话)。我还从ActiveTcl发行版获得了我的Tcl文件。
答案 0 :(得分:0)
我首先看到了相同的链接错误。它只是通过将我的配置从Win32更改为x64来解决。