Hybrid programming of TCL and C

Source: Internet
Author: User

As a scripting language, Tcl is very efficient. Therefore, in actual design, we can use Tcl to complete some tasks that do not have high performance requirements but require a long development cycle to use C, the C language is used only for the part with high execution time requirements.

1. When referencing Tcl in C, the header file <TCL. h> should be included. All tcl commands in c should be completed through the Tcl interpreter tcl_interp. It is a C struct.

The main functions are:

Tcl_interp * tcl_createinterp (); // generate the Tcl Interpreter
Tcl_deleteinterp (tcl_interp * interp); // Delete the Tcl Interpreter
Tcl_interpdeleted (tcl_interp * interp); // checks whether the interpreter has been deleted. If not, a non-zero value is returned.
Tcl_interp * tcl_createslave (tcl_interp * interp, const char slavename, int issafe); // create a slave interpreter. issafe determines whether to create a secure interpreter.
Int tcl_issafe (tcl_interp * interp); // checks whether the interpreter is safe. 1 is returned for security, and 0 is returned for security.
Int tcl_makesafe (tcl_interp * interp); // generate a secure Interpreter
Tcl_interp * tcl_getslave (tcl_interp * interp, const char * slavename); // return from Interpreter
Tcl_interp * tcl_getmaster (tcl_interp * interp); // get the master interpreter from the interpreter
Tcl_interp * terminate (tcl_interp * askinterp, tcl_interp * slaveinterp); // If tcl_ OK is returned successfully, tcl_error is returned. askinterp is set to the path between askinterp and slaveinterp.
I. in TCL, Calling C/C ++ mainly uses C/C ++ to process complex logic. For TCL, it is actually an extension because you can use the tcl_createcommand function, create a new TCL command. Specific operation methods need to be divided into situations: 1. if the current TCL version supports the load command syntax: Load libpackage. so significance: In TCL, when a dynamic library libpackage. when so is loaded, TCL will call the function named package_init. Remember, the name must be case-insensitive. In this way, you get an entry to C/C ++. You can do anything. Of course, the most important thing is tcl_createcommand. Function prototype: tcl_command tcl_createcommand (interp, role name, Proc, clientdata, deleteproc) meaning: Create a New TCL command role name and the corresponding operation function pointer is Proc. Here, we use a factorial algorithm as an example. The purpose is to provide a Tcl command named myfract and only receive one parameter. For example, myfract 10 indicates the factorial of 10. [Fract. c]: # include "TCL. H "int tcl_myfract (clientdata notused, tcl_interp * interp, int argc, char ** argv) {int I, j; double res = 1.0; char re [30]; if (argc> 2) {tcl_setresult (interp, "wrong ARGs: shocould be myfract", tcl_volatile); Return tcl_error;} If (tcl_getint (interp, argv [1], & I )! = Tcl_ OK) {return tcl_error;} For (j = 1; j <= I; j ++) RES * = J; sprintf (Re, "% Le", Res ); tcl_setresult (interp, re, tcl_volatile); Return tcl_ OK;} int fract_init (tcl_interp * interp) {tcl_createcommand (interp, "myfract", (Limit *) limit, (clientdata) 0, 0); Return tcl_ OK;} [makefile]: t = libfract. soall: $ tclean: Rm-F $ t corelibfract. so: fract. c gcc-I. -Shared-O [email protected] fract. c [tes T. TCL ]:#! /Usr/bin/tclshload./libfract. soset tcl_flag [catch {myfract 2} return_str] If {$ tcl_flag! = 0} {puts "OK: $ return_str"} else {puts "error: $ return_str"} Run: Linux :~ /Test/TCL #. /test. tcl2.000000e + 00 [Conclusion]: There are two points to note here. First, fract_init is the entry from TCL to C/C ++, tcl_createcommand is the entry from C/C ++ to TCL. Second, when compiling a dynamic library, you do not need to link to the Tcl development library because it only needs to be referenced here. Also, swig can use [fract. I]: % module fractextern double myfract (INT). the syntax of swig is not described here. For details, see www.swig.org. The first line indicates that the module name is fract, corresponding to the previous C/C ++ code, that is, the dynamic library to be created is called libfract. so; the second line indicates the function to be exported, which needs to be defined by yourself. [Fract. c]: Double myfract (int n) {double res = 1.0; Int J; For (j = 1; j <= N; j ++) {res * = J ;} return (RES);} [makefile]: t = fract_wrap.c libfract. soall: $ tclean: Rm-F $ t core *. doc *. ofract_wrap.c: fract. I swig-tcl fract. ilibfract. so: fract_wrap.c gcc-C fract. c fract_wrap.c run: Linux :~ /Test/Tcl/swig #. /test. tcl2.0 2. if the current TCL version does not support the load command, I don't know which version will be so original, but even so, there is still a solution, that is, to link the extension module to the execution file statically, the specific operation is as follows: [main. c]: # include <TCL. h> # include <stdio. h> int tcl_appinit (tcl_interp * interp); int main (INT argc, char * argv []) {tcl_main (argc, argv, tcl_appinit);} int tcl_appinit (tcl_interp * interp) {/* initialize TCL */If (tcl_init (interp) = tcl_error) {return tcl_error;}/* initialize our extension * /If (fract_init (interp) = tcl_error) {return tcl_error;} return tcl_ OK;} [makefile]: t = maintcl_libs =-L/usr/lib-ltcl8.4all: $ tclean: rm-F $ t coremain: Main. c fract. c gcc-I. $ {tcl_libs}-O [email protected] Main. c fract. c run: Linux :~ /Test/TCL #./main % myfract 84.032000e + 04% exitlinux :~ /Test/TCL # LDD main linux-gate.so.1 => (0xffffe000) libtcl8.4.so =>/usr/lib/libtcl8.4.so (0x40030000) libc. so.6 =>/lib/tls/libc. so.6 (0x400d8000) libdl. so.2 =>/lib/libdl. so.2 (0x401f1000) libm. so.6 =>/lib/tls/libm. so.6 (0x401f5000)/lib/ld-linux.so.2 (0x40000000) We found that the tcl_appinit function was rewritten in the Code and described as a ''hook ''procedure in the Tcl manual, something amazing. Because an execution file similar to tclsh will be created at the end, the Tcl development library must be linked. II. The reason why Tcl is called in C/C ++ is mainly to use Tcl's customization capability. For example, you can write the process in a Tcl script and execute tcl_evalfile in the C/C ++ code. for different services, you can use some means to bind a process script, when a new service is added or the service process needs to be changed, you do not need to modify the source code. You only need to add or modify the configuration file/script file, which is what we call customization. We will only discuss several common functions: tcl_createinterp-create a Tcl interpreter tcl_eval-execute a Tcl command tcl_vareval-similar to tcl_eval, however, this command is a string of tcl_evalfile-execute a Tcl script tcl_setvar-set the Tcl variable tcl_getvar-get the Tcl variable value. The following is a usage test: [test. c]: # include <TCL. h> # include <string. h> # include <stdlib. h> # include <assert. h> int main () {tcl_interp * interp; char * P; int tclres; // create interpreter interp = tcl_createinterp ();/** test tcl_setvar */char * varnam E = "SERVICE_NAME"; char * varval = "myserver"; P = (char *) tcl_setvar (interp, varname, varval, tcl_global_only); Assert (P! = NULL &&! Strncmp (P, "myserver", 8);/** test tcl_getvar */P = (char *) tcl_getvar (interp, "SERVICE_NAME", tcl_global_only); Assert (P! = NULL &&! Strncmp (P, "myserver", 8);/** test tcl_eval */tclres = tcl_eval_r (interp, "set 1__val world"); Assert (tclres = tcl_ OK ); P = (char *) tcl_getvar (interp, "interval _val", tcl_global_only); Assert (P! = NULL &&! Strncmp (P, "world", 5);/** test tcl_vareval */char * home = ". /"; tclres = tcl_vareval_r (interp," Source ", home," test. cfg ", null); Assert (tclres = tcl_ OK); P = (char *) tcl_getvar (interp," interval _val ", tcl_global_only); Assert (P! = NULL &&! Strncmp (P, "hello", 5);/** test tcl_evalfile */char * Path = ". /test. cfg "; tclres = tcl_evalfile (interp, PATH); Assert (tclres = tcl_ OK); P = (char *) tcl_getvar (interp," interval _val ", tcl_global_only ); assert (P! = NULL &&! Strncmp (P, "hello", 5); // end printf ("OK/N");} [makefile ]: T = testtcl_libs =-L/usr/lib-ltcl8.4all: $ tclean: Rm-F $ t coretest: test. c gcc-I. $ {tcl_libs}-O [email protected] test. clinux :~ /Test/Tcl/test #./testok

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.