#include <tcl.h>
#include <stdio.h>
static int fooCmd(ClientData clientData,
         Tcl_Interp *interp, int objc, char * CONST objv[]) {
     printf("called with %d arguments\n", objc);
     return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
     if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
	return TCL_ERROR;
     }
     printf("creating foo command");
     Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL);
     return TCL_OK;
}
My compile.bat (using the current MinGW gcc port):
set djgpp=c:\MinGW\djgpp.env
set path=%path%;c:\MinGW\bin
gcc -I C:\Tcl\include -s -shared -o a.dll a.cpp C:\Tcl\bin\tcl84.dll
pause
First example doesn`t compile. There is an error.
gcc -I C:\Tcl\include -s -shared -o
a.dll a.cpp C:\Tcl\bin\tcl84.dll
a.cpp: In function `int Foo_Init(Tcl_Interp*)':
a.cpp:13: error: invalid conversion from `int (*)(void*, Tcl_Interp*, 
int, char*
  const*)' to `int (*)(void*, Tcl_Interp*, int, Tcl_Obj* const*)'
a.cpp:13: error:   initializing argument 3 of `Tcl_Command_* 
Tcl_CreateObjComman
d(Tcl_Interp*, const char*, int (*)(void*, Tcl_Interp*, int, Tcl_Obj* 
const*), v
oid*, void (*)(void*))'
Example two:
#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);
}
This compiled with same compile.bat without any errors or warnings.
I wanted to compile the second example also with visual studio 
(microsoft C compiler) and I did add the c:\tcl\include and the 
c:\tcl\lib paths. But it doesn`t work, there is an errormessage:
Error 1 error C2664: 'Tcl_CreateObjCommand' : cannot convert parameter 3 
from 'int (__cdecl *)(ClientData,Tcl_Interp *,int,char *const [])' to 
'Tcl_ObjCmdProc (__cdecl *)'
How can I fix it?
You also don`t need to answer this specific question. Any other example 
code which will compile in visual studio and which can be used later as 
a loadable tcl module would be much appreciated.
With that prototype, your fooCmd routine is a
Tcl_CmdProc.  It's a command procedure that takes
string arguments...
> Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL);
...but you are passing fooCmd to
Tcl_CreateObjCommand() and Tcl_CreateObjCommand
expects a Tcl_ObjCmdProc, and not a Tcl_CmdProc.
The compiler is telling you this error.
Either convert your fooCmd routine to be a
Tcl_ObjCmdProc -- a command procedure that
takes (Tcl_Obj *) arguments -- or call
Tcl_CreateCommand() instead of
Tcl_CreateObjCommand().
DGP
I think this problem could compiler based.
Unfortunately what you wrote did not help me.
If you are using in visual studio 7 (2005) or 8 (ocras 2008) yourself 
and get such an extension running, please post the code here.
Michael Reichenbach wrote :
> Well, I got the example from here: 
> http://www.tcl.tk/man/tcl8.4/TclCmd/load.htm#M8. 8.4 is the current 
> stable tcl release and this is the official documentation. Did them use 
> a used wrong commands inside the official documentation example for years?
Definately, documentation is buggy, objv argument should have 
declaration "Tcl_Obj *CONST objv[]", not char*. Error is still there in 
8.4.16-rc1 doc. This may deserve a quick bug report and fix before 
8.4.16 gets out.
> 
> I think this problem could compiler based.
> 
> Unfortunately what you wrote did not help me.
You only need to fix fooCmd declaration:
static int fooCmd(ClientData clientData,
         Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) {
     printf("called with %d arguments\n", objc);
     return TCL_OK;
}
and it will compile fine with mingw, cygwin, vs2k5 or any other 
compiler. I suggests you also define USE_TCL_STUBS=1 
(-DUSE_TCL_STUBS=1), and link with tclstub84.lib instead of tcl84.dll. 
This will make your extension more portable across versions and build 
environments.
> 
> If you are using in visual studio 7 (2005) or 8 (ocras 2008) yourself 
> and get such an extension running, please post the code here.
Eric
1. File -> new project -> name: Foo -> win32 console application -> dll
2. Tools -> Options -> VC++ Directorys -> Include Files -> added 
C:\Tcl\include
3. C++ -> precompiled headers -> Not Using Precompiled Headers
4. Library files -> C:\Tcl\lib
5. Project settings -> Configuration Properties -> Linker -> Input -> 
Additional Dependencies -> added c:\tcl\lib\tclstub84.lib
6. use this source (my mistake was to use the #define after #include) 
(without the extern "C" it`s also not working, you will get error 
message while % load Foo.dll, it says can`t find Foo_Init procedure)
#define USE_TCL_STUBS 1
#include <tcl.h>
#include <stdio.h>
extern "C"
{
	__declspec(dllexport) int Foo_Init(Tcl_Interp* interp);
}
static int fooCmd(ClientData clientData, Tcl_Interp *interp, int objc, 
Tcl_Obj * CONST objv[]) {
	printf("called with %d arguments\n", objc);
	return TCL_OK;
}
int Foo_Init(Tcl_Interp *interp) {
	if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
		return TCL_ERROR;
	}
	printf("creating foo command");
	Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL);
	return TCL_OK;
}
7. Debug -> change to Release
8. Build -> Build solution -> compiles without any errors -> in project 
folder under release is File Foo.dll with ~6 kb