Using Microsoft Visual C++ 6
load tcldemo.dll Tcldemo set tcldemo_version package require Tcldemo
If you don't happen to have a copy of Microsoft's compiler then you can get a copy of GNU C compiled for the win32 platform. The mingw32 project is the minimal approach which uses only the native libraries and so doesn't support unix porting much - see http://sourceforge.net/projects/mingw for the releases.
EXPORTS Tcldemo_Init Tcldemo_SafeInit
g++ -Wall -g -Ii:/opt/Tcl/include -c tcldemo.cpp -o tcldemo.o
dllwrap --driver-name g++ -def tcldemo.def -o tcldemo.dll tcldemo.o -Li:/opt/Tcl/lib -ltcl83 -lm
I've included a suitable Makefile below.
[ Q: isn't it possible to do this without a .def file? I thought the __declspec(dllexport) was supposed to make it unnecessary ]
Dana Robinson: You can use either. You can even have some functions declared as __declspec(dllexport) and other ones specified in a .def file and it'll all work out. Personally, I like to use .def files with platform-independent code. They aren't that hard to maintain and you don't have to mess up your pretty ANSI C/C++ code with a bunch of #ifdefs and MS-specific code.
The code:
#include <windows.h> #include <tcl.h> #ifndef DECLSPEC_EXPORT #define DECLSPEC_EXPORT __declspec(dllexport) #endif // DECLSPEC_EXPORT BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return TRUE; } EXTERN_C int DECLSPEC_EXPORT Tcldemo_Init(Tcl_Interp* interp) { #ifdef USE_TCL_STUBS Tcl_InitStubs(interp, "8.3", 0); #endif Tcl_Obj *version = Tcl_SetVar2Ex(interp, "tcldemo_version", NULL, Tcl_NewDoubleObj(0.1), TCL_LEAVE_ERR_MSG); if (version == NULL) return TCL_ERROR; int r = Tcl_PkgProvide(interp, "Tcldemo", Tcl_GetString(version)); // Call Tcl_CreateObjCommand etc. return r; } EXTERN_C int DECLSPEC_EXPORT Tcldemo_SafeInit(Tcl_Interp* interp) { // We don't need to be specially safe so... return Tcldemo_Init(interp); }
# -*- Makefile -*- for Tcl Demo # # @(#)$Id: 2419,v 1.35 2005-03-22 07:00:24 jcw Exp $ CC =g++ DLLWRAP =dllwrap DLLTOOL =dlltool RM =rm -f CFLAGS =-Wall -Ii:/opt/tcl/include -DUSE_TCL_STUBS LDFLAGS =-Li:/opt/tcl/lib LIBS =-ltclstub83 DLL =tcldemo.dll DEFFILE =tcldemo.def WRAPFLAGS =--driver-name $(CC) --def $(DEFFILE) CSRCS =tcldemo.cpp OBJS =$(CSRCS:.cpp=.o) $(DLL): $(OBJS) $(DLLWRAP) $(WRAPFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) clean: $(RM) *.o core *~ %.o: %.cpp $(CC) $(CFLAGS) -c $< -o $@ .PHONY: clean # # Local variables: # mode: makefile # End: #
This excellent piece of work was created and put here by Pat Thoyts. Thanks Pat!
Paul Kienzle: With recent versions of mingw you can dispense with .def files, DECLSPEC_EXPORT, #include <windows.h>, DllMain, and dllwrap, and just use:
g++ -Wall -g -Ii:/opt/Tcl/include -DUSE_TCL_STUBS -c tcldemo.cpp -o tcldemo.o g++ -shared -o tcldemo.dll tcldemo.o -Li:/opt/Tcl/lib -ltclstub83
After correcting the paths in my Makefile, my tcl extension from unix built and worked fine with ActiveState's binary distribution for windows.
I was unable to produce functional DLL with Paul Kienzles advice, but found another easy way to compile shared library with MinGW for MinGW-compiled Tcl:
gcc -I C:\Tcl\include -s -shared -o test.dll test.c C:\Tcl\bin\tcl84.dll
Apparently newer versions of gcc can extract all required names from the DLL by itself, without using libtclXX.a or libtclstubXX.a. --mjk
( g++.exe can do that, too. But then use a extern "C" block for init and wrapper functions. You can then still call your other C++ functions and create objects, use new and delete etc. and pass the result back to the wrapper function in the extern "C" block. )
See also Building Extensions on Windows.
Question: Once you have built the extensions, where should they be installed, and what gets installed?
Hello!
When compiling Tcldemo with MS Visual Studio .NET I got some errors:
tcldemo error LNK2019: unresolved external symbol __imp__Tcl_PkgProvide referenced in function _Tcldemo_Init tcldemo error LNK2019: unresolved external symbol __imp__Tcl_GetString referenced in function _Tcldemo_Init tcldemo error LNK2019: unresolved external symbol __imp__Tcl_NewDoubleObj referenced in function _Tcldemo_Init tcldemo error LNK2019: unresolved external symbol __imp__Tcl_SetVar2Ex referenced in function _Tcldemo_Init tcldemo fatal error LNK1120: 4 unresolved externals
How to correct these errors?
And after executing
gcc -I C:\Tcl\include -s -shared -o tcldemo.dll tcldemo.c C:\Tcl\bin\tcl84.dll
in Cygwin I could'n load tcldemo.dll, because of this error:
couldn't load library "tcldemo.dll": this library or a dependent library couldn't be found in library path when executing "load tcldemo.dll Tcldemo"
Why does it happen?
Thank you. Anton.