TCL tclOODecls.h未导出的函数

时间:2017-12-08 09:23:35

标签: tcl

我编译的TCL库(Tcl8.6.7,win7)没有导出tclOODecls.h中的函数。我通过在自动生成的部分之前将t if放在tclOODecls.h中来导出函数。

我想知道默认情况下导出函数的原因以及启用导出的首选方法。

1 个答案:

答案 0 :(得分:1)

已将符号定义为使用MODULE_SCOPE。请参阅前面提到过的问题3010352。我们的想法是,如果您想使用这些符号,您应该使用Tcl存根链接机制并定义USE_TCLOO_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].
 */

使用TclOO API使用的静态嵌入Tcl的示例

以下代码将构建一个可执行文件,其作用类似于标准Tcl shell,但包含一个额外的命令,可以作为演示访问TclOO API。

/* 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

可以使用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代码的文件,这些代码可以调用getobjectname并以此文件的路径作为唯一参数运行可执行文件。