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: ======c 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. ======c 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: ======c #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: ======c #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. <> Porting | Windows