Unlike most Unices, on Windows you need to explicitly specify which functions are publically visible when creating a shared library. One way to do this is to write a .DEF file listing the symbols to be exported, and pass that to the linker when building the .DLL. (See the linker documentation for details if you're interested; but the next way is easier). The easier way is to use an MSVC language extension to declare publically visible functions in the source code: extern int __declspec(dllexport) Foo_Init(Tcl_Interp *); ... int __declspec(dllexport) Foo_Init(Tcl_Interp *interp) { ... } Most other compilers for Windows (including the MinGW and CYGWIN versions of gcc) have adopted this extension. Naturally, the ''__declspec(dllexport)'' bit should be hidden inside a preprocessor macro for cross-platform portability. Tcl.h defines such a macro: the symbol ''DLLEXPORT'' expands to the appropriate Windows voodoo if the compilation environment supports it, and to the empty string otherwise. int DLLEXPORT Foo_Init(Tcl_Interp *interp) { ... } ---- That should be sufficient for Tcl extensions' _Init() and _SafeInit() routines. In the general case, though, more preprocessor trickery is needed. Windows also requires that functions appearing in an external shared library be declared with the "__declspec(dllimport)" storage class. Instead of creating two copies of each header file -- one with ''__declspec(dllimport)'' for users of the library and one with ''__declspec(dllexport)'' for the library itself -- the usual idiom is to say: #ifdef BUILD_FOO # define FOOAPI __declspec(dllexport) #else # define FOOAPI __declspec(dllimport) #endif ... extern int FOOAPI foo_fiddle(); extern int FOOAPI foo_faddle(); extern int FOOAPI foo_twaddle(); in the relevant header files, then compile the library with ''-DBUILD_FOO''. Tcl does this, too; the macro ''TCL_STORAGE_CLASS'' expands to ''__declspec(dllexport)'' when building Tcl on Windows, ''__declspec(dllimport)'' when linking directly against the Tcl shared library, and to the empty string when linking with the Stubs library and on non-Windows platforms. Many Tcl extensions use preprocessor contortions like: #undef TCL_STORAGE_CLASS #ifdef BUILD_sampleextension # define TCL_STORAGE_CLASS DLLEXPORT #endif ... EXTERN int Sample_Init(); ... This is overly complex and error-prone; I recommend not doing this. Basically, this is hijacking Tcl's preprocessor voodoo for reuse by other packages. It's simpler, clearer, and safer for extensions to just define their own voodoo. [Category Porting]