Building the Hello C Extension using Visual Studio 2010 express

stevieb - 2011-07-11 20:06:44

The following instructions demonstrate how to successfully build the Hello.c extension using Visual Studio 2010 Express Edition [L1 ] from the command line, as I received errors when trying to compile and link hello.c on Windows, from the examples on the Hello World as a C Extension page, both compile and link commands had problems. so to help anyone else who tries to build hello.c or any C extensions on windows here's what I did to correct the commands and successfully compile and link hello.c using Microsoft Visual Studio 2010 Express Edition and then ultimately use the extension:

1. Right clicked on Start->My Computer, then in System Properties->Advanced tab in "Environment Variables" created the environment variable TCLINC with value C:\Tcl\include, and TCLLIB with value C:\Tcl\Lib which will point to the TCL include and TCL lib folder locations on my system. Applied the settings and OK'd System setup.

2. Opened a new command window (important you cant use the one already had one open this wont have access to any new environment variables)

3. Modified the compile command to reference the TCLINC environment variable as shown:

   cl -nologo -W3 -O2 -MD -DUSE_TCL_STUBS -I%TCLINC% -c hello.c

4. Run the compile command and received the following error, note that at least compiler has now found tcl.h, but tcl.h depends on C standard io header stdio.h, which it clearly cant find:

   hello.c
   C:\Tcl\include\tcl.h(141) : fatal error C1083: Cannot open include file: 'stdio.h': No such file or directory

5. Added the path to the c header stdio.h, to the system environment variable path and opened a new command prompt to use the new path, but for some unknown reason, the visual studio command can't find it in the path: on to plan B next:

   path:
   C:\Tcl\bin;C:\Program Files\ActiveState Komodo Edit 6\;C:\php\;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32
   \Wbem;C:\Program Files\MySQL\MySQL Server 5.5\bin;c:\ruby191\bin;C:\ruby;C:\Program Files\Microsoft Visual Studio
   10.0\VC\bin;C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE;C:\Program Files\Microsoft Visual Studio 10.0\VC
   \include

6. Plan B - run the Visual Studio.bat files to set up the Visual C environment in my command window session, to make available, all paths to required C includes and libraries until I work out why in the world the path isn't being read?, this worked in previous VC++ Express Editions, but they seem to be getting less and less powerful with each edition! Anyway it may be that only one of the following commands is required to do the trick, but I included both for good measure:

   "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
   Setting environment for using Microsoft Visual Studio 2010 x86 tools.

   "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
   Setting environment for using Microsoft Visual Studio 2010 x86 tools.

7. Finally managed to compile hello.c successfully as follows:

   cl -nologo -W3 -O2 -MD -DUSE_TCL_STUBS -I%TCLINC% -c hello.c
   hello.c

This successfully generates the obj file hello.obj and now we can do the linking.

8. There was a problem with the link command, it wouldn't recognize my %TCLLIB% environment variable, I couldn't work out why, the path looked fine to me? so I just entered the full path as shown and that did the trick:

   link -nologo -release -dll -out:hello.dll hello.obj -libpath:c:\TCL\lib tclstub85.lib
   Creating library hello.lib and object hello.exp

   and thats how to build the extension, if all goes well you should end up with the following files:
   hello.c
   hello.dll
   hello.exp
   hello.lib
   hello.obj

9. Finally to use the extension run the following commands, note on Windows there is no need to specify the extension as I know that the load command is expecting to load a dll on Windows, so if you just put hello the load will do the rest, for example let us demonstrate this by specify the wrong extension, when using the load command:

    C:\> tclsh
    % load hello.lib[info sharedlibextension]
     couldn't load library "hello.lib.dll": this library or a dependent library could not be found in library path

    Note: the first commmand tclsh loads the TCL-shell (a command line interface to run TCL commands, you will know you are
          in the shell as the prompt will change to %).  For the load command I deliberately provided the ''lib''
          extension and received the error, also note the error says could not load "hello.lib.dll", confirming that
          load is expecting a file with a .dll extension and also note the file extension is added by the load command

   Ok so now lets actually load the C extension:

   % load hello[info sharedlibextension]

   And finally lets use the C extension:

   % hello
   Hello, World!

   It may seem like a lot of effort to produce 2 simple words, but this example was useful to learn how to build a C
   extension now hopefully now you can build some really useful C extensions.

I hope this helps anyone else who has problems building the example on Windows, which always seemingly complicates things which are concise and trivial on Unix/Linux systems! Incidentally I wasnit already a member but through no fault of mine I was asked to create a user, I put steveb as my username, I got no error codes back telling me the username was already used, I was not prompted for a password, but when I followed the "whoami" link it turns out the system thinks I am Steve Bennett, but I am not, apologies to Steve Bennnet. The page Hello World as a C extension has been really helped get me started, it's a pity there wasn't also a good example on C Callbacks from a TK GUI.

Apology accepted! (The real Steve Bennett - note the double t)

Double t, right got it, I have now created a new user, which doesn't appear to be taken by anyone else.