Seems fine to me.
I created the following Tcl extension to perform your Tcl_Eval:
#include <tcl.h>
static int
DotestCmd(ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[])
{
return Tcl_Eval(interp, "source test_namespace.tcl");
}
int DLLEXPORT
Testnamespace_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "dotest", DotestCmd, NULL, NULL);
return Tcl_PkgProvide(interp, "testnamespace", "1.0");
}
Being on windows, I compiled this using:
cl -nologo -W3 -O2 -MD -DNDEBUG -DUSE_TCL_STUBS -I\opt\tcl\include -c test_namespace.c
link -dll -release -out:testnamespace.dll test_namespace.obj \opt\tcl\lib\tclstub85.lib
and then created a test_namespace.tcl file with the content you posted above. Running this produces the following:
C:\opt\tcl\src>tclsh
% load testnamespace.dll Testnamespace
% dotest
Namespace calling ::bob::proc2
%
and further introspection shows things are as I would expect from that script:
% namespace children ::
::platform ::activestate ::bob ::tcl
% namespace children ::bob
::bob::joe
%
You probably are doing something weird in your C code first if this is really not working for you.
Update
The above example is for extending tcl with a compiled package. Apparently the OP is embedding Tcl into some other application. A trivial example of doing this is provided here which also runs the same command to the same effect as above. In reality when embedding Tcl into an application the code should use the tclAppInit.c file and provide its own Tcl_AppInit function. By running the usual Tcl_Main you get the full capabilities for processing events (needed for fileevents or after commands) and the interactive shell. An example of that follows the trivial version:
/* trivial embedding Tcl example */
#include <tcl.h>
#include <locale.h>
int
main(int argc, char *argv[])
{
Tcl_Interp *interp = NULL;
int r = TCL_ERROR;
setlocale(LC_ALL, "C");
interp = Tcl_CreateInterp();
if (interp != NULL) {
Tcl_FindExecutable(argv[0]);
r = Tcl_Eval(interp, "source test_namespace.tcl");
if (TCL_OK == r)
r = Tcl_Eval(interp, "puts [namespace children ::bob]");
Tcl_DeleteInterp(interp);
}
return r;
}
Running the above:
C:\opt\tcl\src>cl -nologo -W3 -O2 -MD -I\opt\tcl\include test_namesp_embed.c -link -subsystem:console -release -libpath:\opt\tcl\lib tcl85.lib
test_namesp_embed.c
C:\opt\tcl\src>test_namesp_embed.exe test_namespace.tcl
Namespace calling ::bob::proc2
::bob::joe
A better embedding scheme that uses tclAppInit to extend a stock Tcl interpreter:
#include <tcl.h>
#include <locale.h>
#define TCL_LOCAL_APPINIT Custom_AppInit
int
Custom_AppInit(Tcl_Interp *interp)
{
return Tcl_Eval(interp, "source test_namespace.tcl");
}
#include "/opt/tcl/src/tcl.git/win/tclAppInit.c"
Building and running this also produces the same output as previous versions:
C:\opt\tcl\src>cl -nologo -W3 -O2 -MD -I\opt\tcl\include test_namesp_embed.c -link -subsystem:console -release -libpath:\opt\tcl\lib tcl85.lib
C:\opt\tcl\src>test_namesp_embed.exe
Namespace calling ::bob::proc2
% namespace children ::bob
::bob::joe
% exit