TCL tclOODecls.h函数未导出

TCL tclOODecls.h函数未导出,tcl,Tcl,我编译的TCL库(Tcl8.6.7,win7)没有导出tclOODecls.h中的函数。我通过将:#define TCLAPI extern DLLEXPORT放在tclOODecls.h中的自动生成部分之前导出了这些函数 我想知道为什么默认情况下不导出函数,以及启用导出的首选方式。符号已定义为使用模块范围。请看刚才提到这一点的问题。其思想是,如果要使用这些符号,应该使用Tcl stubs链接机制,并定义use_TCLOO_stubs宏和stubs库的链接(tclstub86)。函数在那里-只是

我编译的TCL库(Tcl8.6.7,win7)没有导出tclOODecls.h中的函数。我通过将:
#define TCLAPI extern DLLEXPORT
放在tclOODecls.h中的自动生成部分之前导出了这些函数


我想知道为什么默认情况下不导出函数,以及启用导出的首选方式。

符号已定义为使用模块范围。请看刚才提到这一点的问题。其思想是,如果要使用这些符号,应该使用Tcl stubs链接机制,并定义use_TCLOO_stubs宏和stubs库的链接(tclstub86)。函数在那里-只是没有在DLL导出上导出

来自tcl.h:

/*
 * Include platform specific public function declarations that are accessible
 * via the stubs table. Make all TclOO symbols MODULE_SCOPE (which only
 * has effect on building it as a shared library). See ticket [3010352].
 */
使用tclooapi静态嵌入Tcl的示例 下面的代码将构建一个可执行文件,它的工作方式类似于标准Tcl shell,但包含一个额外的命令,该命令作为演示访问tclooapi

/* Demonstrate embedding Tcl and using the TclOO API.
 *
 * Build with MSVC (adjust paths for local setup):
 *
 *   cl -nologo -W3 -MT -Zi -GL -DSTATIC_BUILD -Ic:\opt\tcl\include test_embed_oo.c \
 *      -Fe:test_embed_oo.exe -link -debug -subsystem:console -ltcg -libpath:C:\src\tcl\kitgen\8.6\tcl\win\Release_VC13 \
 *      tcl86ts.lib user32.lib ws2_32.lib netapi32.lib
 *
 * Requires a static libary if Tcl (tcl86ts.lib on windows)
 */
#include <tcl.h>
#include <tclOO.h>
#include <locale.h>

static int
GetObjectNameCmd(ClientData clientData, Tcl_Interp *interp,
                 int objc, Tcl_Obj *const objv[])
{
    int r = TCL_ERROR;
    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "object");
        return r;
    }
    Tcl_Object object = Tcl_GetObjectFromObj(interp, objv[1]);
    if (object != NULL) {
        Tcl_Obj *resultObj = Tcl_GetObjectName(interp, object);
        if (resultObj != NULL) {
            Tcl_SetObjResult(interp, resultObj);
            r = TCL_OK;
        }
    }
    return r;
}

#define TCL_LOCAL_APPINIT Custom_AppInit
int
Custom_AppInit(Tcl_Interp *interp)
{
    Tcl_CreateObjCommand(interp, "getobjectname", GetObjectNameCmd, NULL, NULL);
    return Tcl_Eval(interp, "source test_embed_oo.tcl");
}

#include "c:/src/tcl/kitgen/8.6/tcl/win/tclAppInit.c"
/*演示嵌入Tcl和使用TCLOOAPI。
*
*使用MSVC构建(调整本地设置的路径):
*
*cl-nologo-W3-MT-Zi-GL-DSTATIC_BUILD-Ic:\opt\tcl\include test_embed_oo.c\
*-Fe:test\u embed\u oo.exe-link-debug-subsystem:console-ltcg-libpath:C:\src\tcl\kitgen\8.6\tcl\win\Release\u VC13\
*tcl86ts.lib user32.lib ws2_32.lib netapi32.lib
*
*如果是Tcl,则需要静态库(windows上的tcl86ts.lib)
*/
#包括
#包括
#包括
静态整数
GetObjectNameCmd(ClientData客户端数据,Tcl_Interp*Interp,
int objc,Tcl_Obj*常量objv[]
{
int r=TCL_错误;
如果(objc!=2){
Tcl_错误数字标记(interp,1,objv,“对象”);
返回r;
}
Tcl_Object Object=Tcl_GetObjectFromObj(interp,objv[1]);
if(对象!=NULL){
Tcl_Obj*resultObj=Tcl_GetObjectName(interp,object);
如果(resultObj!=NULL){
Tcl_SetObjResult(interp,resultObj);
r=TCL_正常;
}
}
返回r;
}
#定义TCL\u LOCAL\u APPINIT Custom\u APPINIT
int
自定义应用程序初始化(Tcl\u Interp*Interp)
{
Tcl_CreateObjCommand(interp,“getobjectname”,GetObjectNameCmd,NULL,NULL);
返回Tcl_Eval(interp,“源代码测试嵌入oo.Tcl”);
}
#包括“c:/src/tcl/kitgen/8.6/tcl/win/tclAppInit.c”
使用动态加载嵌入Tcl Tcl可以使用Tcl存根链接机制动态链接到应用程序。这需要从DLL加载两个函数,然后初始化存根表。下面显示了启用TclOO访问时的情况

/* Demonstrate embedding Tcl and using the TclOO API via stubs
 *
 * Build with MSVC (adjust paths for local setup):
 *
 *   cl -nologo -W3 -MD -Zi -GL -Ic:\opt\tcl\include test_embed_oo_ex.c \
 *      -Fe:test_embed_oo_ex.exe -link -debug -ltcg -subsystem:console \
 *      -libpath:C:\opt\tcl\lib tclstub86.lib user32.lib
 *
 * Dynamically loads Tcl and then uses stubs for API access.
 */

#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include <locale.h>

#define USE_TCL_STUBS
#define USE_TCLOO_STUBS
#include <tcl.h>
#include <tclOO.h>

static int
GetObjectNameCmd(ClientData clientData, Tcl_Interp *interp,
                 int objc, Tcl_Obj *const objv[])
{
    int r = TCL_ERROR;
    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "object");
        return r;
    }
    Tcl_Object object = Tcl_GetObjectFromObj(interp, objv[1]);
    if (object != NULL) {
        Tcl_Obj *resultObj = Tcl_GetObjectName(interp, object);
        if (resultObj != NULL) {
            Tcl_SetObjResult(interp, resultObj);
            r = TCL_OK;
        }
    }
    return r;
}

typedef Tcl_Interp *(*LPFNTCLCREATEINTERP)();
typedef void *(*LPFNTCLFINDEXECUTABLE)(const char *);

static Tcl_Interp *
InitializeTcl(int argc, char *argv[])
{
    Tcl_Interp *interp = NULL;
    //Tcl_DString dString;
    char szLibrary[16];
    int nMinor;
    HINSTANCE hTcl = NULL;

    for (nMinor = 6; hTcl == NULL && nMinor > 4; nMinor--) {
        wsprintfA(szLibrary, "tcl8%d.dll", nMinor);
        hTcl = LoadLibraryA(szLibrary);
    }

    if (hTcl != NULL) {
        LPFNTCLCREATEINTERP lpfnTcl_CreateInterp;
        LPFNTCLFINDEXECUTABLE lpfnTcl_FindExecutable;
        lpfnTcl_CreateInterp = (LPFNTCLCREATEINTERP)
            GetProcAddress(hTcl, "Tcl_CreateInterp");
        lpfnTcl_FindExecutable = (LPFNTCLFINDEXECUTABLE)
            GetProcAddress(hTcl, "Tcl_FindExecutable");
        if (lpfnTcl_CreateInterp != NULL) {
            interp = lpfnTcl_CreateInterp();
            if (interp != NULL) {
                Tcl_InitStubs(interp, "8.6", 0);
#ifdef USE_TCLOO_STUBS
                Tcl_OOInitStubs(interp);
#endif
                lpfnTcl_FindExecutable(argv[0]);
                Tcl_InitMemory(interp);
                Tcl_Init(interp);
            }
        }
    }
    return interp;
}
/*
 * Embed tcl interpreter into a C program.
 */
int
main(int argc, char *argv[])
{
    Tcl_Interp *interp = NULL;
    int r = TCL_ERROR;

    setlocale(LC_ALL, "C");
    interp = InitializeTcl(argc, argv);
    if (interp == NULL) {
        fprintf(stderr, "error: failed to initialize Tcl runtime\n");
    } else {
        Tcl_CreateObjCommand(interp, "getobjectname", GetObjectNameCmd, NULL, NULL);
        if (argc > 1) {
            r = Tcl_EvalFile(interp, argv[1]);
            printf(Tcl_GetStringResult(interp));
        }
        Tcl_DeleteInterp(interp);
    }
    return r;
}
/*演示如何通过存根嵌入Tcl和使用tclooapi
*
*使用MSVC构建(调整本地设置的路径):
*
*cl-nologo-W3-MD-Zi-GL-Ic:\opt\tcl\include test\u embed\u oo\u ex.c\
*-Fe:test_embed_oo_ex.exe-link-debug-ltcg-子系统:控制台\
*-libpath:C:\opt\tcl\lib tclstub86.lib user32.lib
*
*动态加载Tcl,然后使用存根进行API访问。
*/
#定义WIN32_精益_和_平均值
#定义严格
#包括
#包括
#定义使用\u TCL\u存根
#定义USE_TCLOO_存根
#包括
#包括
静态整数
GetObjectNameCmd(ClientData客户端数据,Tcl_Interp*Interp,
int objc,Tcl_Obj*常量objv[]
{
int r=TCL_错误;
如果(objc!=2){
Tcl_错误数字标记(interp,1,objv,“对象”);
返回r;
}
Tcl_Object Object=Tcl_GetObjectFromObj(interp,objv[1]);
if(对象!=NULL){
Tcl_Obj*resultObj=Tcl_GetObjectName(interp,object);
如果(resultObj!=NULL){
Tcl_SetObjResult(interp,resultObj);
r=TCL_正常;
}
}
返回r;
}
typedef Tcl_Interp*(*lpfntlcreateinterp)();
typedef void*(*LPFNTCLFINDEXECUTABLE)(常量字符*);
静态Tcl_Interp*
InitializeTcl(int argc,char*argv[])
{
Tcl_Interp*Interp=NULL;
//TCLdstring;
字符库[16];
国际货币基金组织;
HINSTANCE hTcl=NULL;
对于(nMinor=6;hTcl==NULL&&nMinor>4;nMinor--){
wsprintfA(szLibrary,“tcl8%d.dll”,nMinor);
hTcl=LoadLibraryA(szLibrary);
}
如果(hTcl!=NULL){
LPFNTCLEATEINTP LPFNTCLEATEINTP;
LPFNTCLFINDEXECUTABLE LPFNTCLFINDEXECUTABLE;
lpfnTcl_CreateInterp=(lpfntlcreateinterp)
GetProcAddress(hTcl,“Tcl_CreateInterp”);
lpfnTcl_FindExecutable=(LPFNTCLFINDEXECUTABLE)
GetProcAddress(hTcl,“Tcl_FindExecutable”);
if(lpfnTcl_CreateInterp!=NULL){
interp=lpfnTcl_CreateInterp();
如果(interp!=NULL){
Tcl_InitStubs(interp,“8.6”,0);
#ifdef使用_TCLOO_存根
Tcl_OOInitStubs(interp);
#恩迪夫
lpfnTcl_FindExecutable(argv[0]);
Tcl_InitMemory(interp);
Tcl_Init(interp);
}
}
}
返回interp;
}
/*
*将tcl解释器嵌入到C程序中。
*/
int
main(int argc,char*argv[])
{
Tcl_Interp*Interp=NULL;
int r=TCL_错误;
setlocale(LC_ALL,“C”);
interp=初始值(argc,argv);
if(interp==NULL){
fprintf(stderr,“错误:初始化Tcl运行时失败\n”);
}否则{
Tcl_CreateObjCommand(interp,“getobjectname”,GetObjectNameCmd,NULL,NULL);
如果(argc>1){
r=Tcl_EvalFile(interp,argv[1]);
printf(Tcl_GetStringResult(interp));
}
Tcl_DeleteInterp(interp);
}
返回r;
}

要测试这一点,您需要一个包含一些tcl代码的文件,这些代码可以调用
getobjectname
,并以该文件的路径作为唯一参数运行可执行文件。

谢谢您的回答。如果要将TCL库嵌入到另一个应用程序(例如C++)中,那么导出方法是否有任何不同?如果要嵌入TCL库,那么您是静态编译并直接链接进来的。我认为MODULE_SCOPE宏应该会使OO函数对链接应用程序可见。Tcl库是一个dll,我检查过(这是在我工作之前)