Posted to tcl by patthoyts at Wed Apr 08 14:10:37 GMT 2009view pretty
/* basethrd.c - Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net> * * Sample of an embedded Tcl application linked using the Tcl stubs mechanism * as seen at http://wiki.tcl.tk/2074. * * This version demonstrates linking to the stardll (ActiveTcl calls it a * basekit DLL) which is a TclKit presented as a DLL. * * This will create two threads and load a given basekit dll library on * each. * * can be built using: * cl -MD -W3 -I/opt/tcl/include basethrd.c \opt\tcl\lib\tclstub85.lib * * ---------------------------------------------------------------------- * This source code is public domain. * ---------------------------------------------------------------------- * * $Id$ */ #define STRICT #define WIN32_LEAN_AND_MEAN #include <windows.h> #ifndef USE_TCL_STUBS #define USE_TCL_STUBS #endif #include <tcl.h> static Tcl_Interp *InitializeTcl(const char *dllname,int argc, char *args[]); typedef struct Init { const char *path; int argc; char **argv; DWORD tid; } Init; DWORD WINAPI BeginThread(LPVOID pClientData) { Init *pInit = pClientData; Tcl_Interp *interp; int r = TCL_OK; interp = InitializeTcl(pInit->path, pInit->argc, pInit->argv); if (interp == NULL) { fprintf(stderr, "error: failed to initialize Tcl\n"); } else { if (pInit->argc > 1) { r = Tcl_EvalFile(interp, pInit->argv[1]); printf(Tcl_GetStringResult(interp)); } Tcl_DeleteInterp(interp); } return r; } int main(int argc, char *argv[]) { HANDLE threads[2]; Init init[2]; int n; init[0].path = "basekit.dll"; init[1].path = "basekit85.dll"; for (n = 0; n < sizeof(threads)/sizeof(threads[0]); ++n) { init[n].argc = argc; init[n].argv = argv; threads[n] = CreateThread(0, 0, BeginThread, &init[n], CREATE_SUSPENDED, &init[n].tid); } /* start the threads */ for (n = 0; n < sizeof(threads)/sizeof(threads[0]); ++n) ResumeThread(threads[n]); while (1) { DWORD dwWait = WaitForMultipleObjects(n, threads, TRUE, 1000); if (dwWait == WAIT_TIMEOUT) { printf("tick\n"); } else if (dwWait >= WAIT_OBJECT_0 && dwWait < (WAIT_OBJECT_0 + n)) { break; } else { fprintf(stderr, "error!\n"); break; } } /* cleanup politely */ for (n = 0; n < sizeof(threads)/sizeof(threads[0]); ++n) CloseHandle(threads[n]); return 0; } typedef Tcl_Interp * (*LPFNCREATEINTERP) (); typedef int (*LPFNBASEKITINIT) (Tcl_Interp *); typedef char * (*LPFNSETKITPATH) (char *); Tcl_Interp * InitializeTcl(const char *dllname, int argc, char *argv[]) { WCHAR szLibrary[MAX_PATH]; CHAR utfLibrary[MAX_PATH * 2]; HINSTANCE hTcl = NULL; Tcl_Interp *interp = NULL; hTcl = LoadLibraryA(dllname); if (hTcl != NULL) { LPFNCREATEINTERP lpfnCreateInterp = (LPFNCREATEINTERP)GetProcAddress(hTcl, "Tcl_CreateInterp"); LPFNBASEKITINIT lpfnBasekitInit = (LPFNBASEKITINIT)GetProcAddress(hTcl, "TclKit_AppInit"); LPFNSETKITPATH lpfnSetKitPath = (LPFNSETKITPATH)GetProcAddress(hTcl, "TclKit_SetKitPath"); if (lpfnCreateInterp != NULL && lpfnBasekitInit != NULL && lpfnSetKitPath != NULL) { interp = lpfnCreateInterp(); if (interp != NULL) { Tcl_InitStubs(interp, "8.4", 0); Tcl_FindExecutable(argv[0]); GetModuleFileNameW(hTcl, szLibrary, MAX_PATH); WideCharToMultiByte(CP_UTF8, 0, szLibrary, -1, utfLibrary, MAX_PATH*2, NULL, NULL); lpfnSetKitPath(utfLibrary); if (lpfnBasekitInit(interp) == TCL_OK) { Tcl_InitMemory(interp); } else { fprintf(stderr, "TclKit_AppInit: %s\n", Tcl_GetStringResult(interp)); } } } } return interp; }