Interactive and Interpretive Execution Of C/C++ Functions and Programs
Not only C statements and expressions, but also C functions and programs, can be interactively executed in Ch. All functions in the C Standard Libraries can be executed interactively and used inside user-defined functions. For example, in Example 2, the random-number generator function rand()
is seeded with a time value in srand(time(NULL)
. Function add()
, which calls type-generic mathematical function sin()
, is defined at the prompt and then used.
Example 2: Using C Standard Library functions from the command line.
> srand(time(NULL)) > rand() 4497 > rand() 11439 > double add(double a, double b) {double c; return a+b+sin(1.5);} > double c > c = add(10.0, 20) 30.9975
A function can also be invoked from a function file. A function file in Ch is a file with the extension .chf that contains only one function definition. The names of the function file and function definition inside the function file must be the same. A function is searched based on the search paths in the system variable _fpath
for function files. The system variables can be set up in the startup configuration file .chrc for UNIX and _chrc in Windows in the user's home directory. For example, Listing One is the function file addition.chf for function addition()
.
Listing One
/* File: addition.chf */ int addition(int a, int b) { int c; c = a + b; return c; }
If file addition.chf is located in a directory specified in _fpath
, function addition()
can be used inside a program or command line:
> int i = 10 > i = addition(10, i) 20
All functions, including function main()
, in C are at the same level; functions cannot be defined inside other functions. In other words, there are no internal procedures in C. Ch extends C with nested functions.
Listing Two
/* File: nestedfunc.chf */ int nestedfunc(int a, int b) { int innerfunc(int i, int j) { int k; k = 2*(i+j); return k; } int c; c = innerfunc(a, b); return c; }
A function can define other functions inside itself. For example, the nested function nestedfunc()
defined in Listing Two can be executed interactively as follows:
> nestedfunc(10, 20) 60
where function innerfunc()
is defined inside function nestedfunc()
. With nested functions, details of one functional module can be hidden from the other modules that do not need to know about them. Each module can be studied independent of others. Software maintenance is the major cost of a program. People who were not involved in the original design often do the most program maintenance. Nested functions modularize a program, thus clarifying the whole program and easing the pain of making changes to modules written by others. Nested functions are useful for information hiding and modular programming. They are complementary to data encapsulation in object-oriented programming in C++. In some applications, using nested functions is simpler than using member functions of classes.
Classes and some other C++ features are also supported in Ch for interactive execution of C++ code, as shown in Example 3.
Example 3: Some C++ features are supported in Ch for interactive execution of C++ code.
> int i > cin >> i 10 > cout << i 10 > class tagc {private: int m_i; public: void set(int); int get(int &);} > void tagc::set(int i) {m_i = 2*i;} > int tagc::get(int &i) {i++; return m_i;} > tagc c > c.set(20) > c.get(i) 40 > i 11 > sizeof(tagc) 4
The input and output can be handled using cin
and cout
in C++. The public method tagc::set()
sets the private member field m_i
, whereas the public method tagc::get()
gets its value. The argument of method tagc::get()
is passed by reference. The size of the class tagc
is 4 bytes, which does not include the memory for member functions.
Listing Three
/* File: hello.c */ #include <stdio.h> int main() { printf("Hello, world\n"); return 0; }
C/C++ programs can also be executed interactively without compilation. For example, to run the program hello.c in Listing Three, one can type the command hello.c in a Ch command shell to get the output of "Hello, world":
> hello.c Hello, world
Ch finds executable commands in directories specified in the system variable _path
. From other command shells, program hello.c can be executed in Ch without compilation, as follows:
% ch hello.c
C/C++ programs can also run in Ch from an Integrated Development Environment (IDE) with a graphical user interface (GUI). Many IDEs, including the open-source ChSciTE IDE shown in Figure 3, support Ch by default. ChSciTE has a native graphical user interface in more than 30 localized languages.
Figure 3: Editing and running a program using ChSciTE IDE.
To speed up interpretive execution of a C program, one should try to avoid loops in the program. For scientific numerical computations, one can use computational arrays for fast execution of algorithms with arrays. Alternatively, the code that is computationally intensive in a script program can be compiled as a binary module. In general, you may find it is necessary to interface binary modules in the following situations:
- The source code of a C/C++ library is not available.
- To run Ch scripts fast by making the frequently called underlying C/C++ functions a binary library.
- To protect the intellectual property and source code from being revealed.
The Ch Software Development Kit (SDK) included in the distribution of Ch allows C/C++ scripts (Ch scripts) to interface C/C++ binary libraries without recompilation. C functions dlopen()
, dlsym()
, dlerror()
, dlclose()
, and Ch extension function dlrunfun()
are used to dynamically load binary modules. They allow Ch scripts to access global variables or call functions in the compiled C/C++ libraries such as static library, shared library, or dynamically linked library (DLL). Ch scripts can callback Ch functions from C/C++ libraries. There is no distinction between the interpreted and compiled code.
The Ch SDK provides a utility to generate wrappers for Ch to interface C/C++ libraries automatically. Ch SDK has been effectively used to interface with Standard C Libraries such as POSIX, X11/Motif, Win32, GTK+, OpenGL, and ODBC.
The interpretive execution of C functions and programs is suitable for applications that do not take very much CPU time. Unlike other scripting languages, as a superset of C, Ch is particularly suitable for applications that need to interface to hardware, such as automated hardware testing and diagnosis.
The interpretive execution of C functions and programs is ideal for rapid prototyping. Programs can first be developed and tested in Ch. Later, the same code can be compiled in a C or C++ compiler for final production. Applications with tens of thousands of lines using functions in libraries such as POSIX, X11/Motif, Win32, GTK+, OpenGL, and ODBC can also effectively run in Ch.
The program compilation presents a serious problem for real-time manipulation of mechatronic systems. For real-time mechatronic systems, the external environment may be different at each execution, so the testing scenario may not be repeatable. During debugging and testing, it is impractical to restart a program from the very beginning every time a change is made or a problem is diagnosed. Ch is time deterministic. It can be used for control of mechatronic systems such as robotics. In a typical real-time application in RTLinux, a hard real-time module runs in the Linux kernel; Ch runs in the user space and communicates with the real-time module through interprocess communication such as FIFO.
The interpretive execution of C programs is especially suitable for interactive presentations using a laptop in a classroom with a quick response. With an interactive computing environment, instructors can relieve themselves from tedious compile/link/execute/debug cycles, and focus on teaching the knowledge and problem-solving skills. All sample code in a textbook for teaching computer programming in C can readily run in Ch without modification.
Ch is especially suitable for developing web-based interactive content in engineering and science for general applications and distance learning. For example, web-based design and analysis of control systems and mechanisms have been developed and they are available online at http://www.softintegration.com/ webservices/. The shopping cart on this site was also developed in Ch.
Conclusion
Ch is a complete C interpreter. It supports most new features added in C99 and classes in C++. Ch is embeddable in other applications as a C/C++ scripting engine. It is ideal for cross-platform scripting, shell programming, 2D/3D plotting, numerical computing, and embedded scripting. C/Ch/C++ allow users to use one language, anywhere and everywhere, for any programming tasks. Ch lowers the barrier for system programmers to do scripting. Whether you are a novice computer user or experienced C/C++ programmer, I hope that Ch will make your programming tasks more enjoyable.
Acknowledgment
I would like to thank Tom MacDonald for his suggestions and comments on this article.
Reference
- Ch: An Embeddable C/C++ Interpreter, http://www.softintegration.com/.
Harry H. Cheng is a professor and director of the Integration Engineering Laboratory at the University of California, Davis. He is the Chief Architect of Ch, an embeddable C/C++ interpreter for script computing. He can be reached at [email protected].