C, C++, D Source Code Blocks in Org Mode
Introduction
Babel can evaluate C, C++, and D code.
As opposed to interpreted languages, which can be evaluated directly, C, C++, and D code is first compiled to an executable which is then run.
If a main
method is not present in a code block then the entire
block is wrapped in a trivial main
function call.
Note: there used to be two separate library files, ob-C.el
and
ob-D.el
. They have been merged in a single ob-C.el
file which
handle all three languages.
So, for example, the following simple code block can be evaluated and the results of evaluation inserted into the buffer.
#+begin_src C++ :includes <stdio.h> int a=1; int b=1; printf("%d\n", a+b); #+end_src #+results: : 2
About C
C dates back to the 1970's. It was devised by Kernighan and Ritchie. It was used to create the Unix kernel, and many of its utilities. Today it is still the base of the Linux and Unix kernels.
About C++
C++ was devised by Stroustrup in the 1980. The purpose was to enhance C with object programming. Among the features introduced by C++, there are:
- templates and the Standard Template Library;
- object programming, with class definition and inheritance;
- functions and operators overloading; and
- exceptions.
About D
D is a C++-like language made by Digital Mars. It features:
- C++ syntax;
- built-in garbage collector;
- strong type system;
- meta-programming;
- seamless assembler support;
- usable as a scripting language; and
- C binary compatibility.
Requirements and Setup
You must have the compilers available on your computer. You may use only one of the three languages: there is no requirement to have all three installed.
- C and C++ often come pre-installed.
Popular compilers are the GNU ones, called
gcc
andg++
. But others are usable as well. - For D, look at http://dlang.org/ for downloading and instructions.
The compilers are called
dmd
andrdmd
.
Eventually, the compilers must be in the
PATH
.- C and C++ often come pre-installed.
Popular compilers are the GNU ones, called
Make any or all languages available to Babel. Type:
M-x customize-variable org-babel-load-languages
and add the C language (capital "C", which gives access to C, C++, D)
Default are given for the compilers:
gcc
,g++
,rdmd
. They may be customized. Type:M-x customize-group org-babel
and look for
Org Babel C++ Compiler
and such.
Org Mode Features for C, C++, D Source Code Blocks
Header Arguments
:var VARIABLE=VALUE
A global C, C++, or D variable named VARIABLE will be declared and initialized with VALUE.
Possible types for VARIABLE may be:
int, double, string or const char*, type[] // type = int, double, string, const char* type[][] // type = int, double, string, const char*
The latter type,
type[][]
, is used for variables storing Org tables.The
type[]
is used for lists or vectors declared in the header.:cmdline
- command line arguments to pass to the executable compiled from the code block.
:flags
- flags to pass to the compiler.
:main
- can be set to "no" to inhibit wrapping of the code block
in a
main
function call. :includes
- (C & C++ only)
accepts either a single string name, or a list of
names of files to
#include
in the execution of the code block. :import
- (D only) An import statement will be declared in the D source before the source code.
:defines
- (C & C++ only) just like
:includes
but for#defines
lines at the top of the code. :namespaces
- (C++ only)
accepts either a single name, or a list of names of namespaces to use.
The final format will look like this:
using namespace name;
:libs
- (C & C++ only) useful for linking with a library, may be given
-L/path/to/lib
and-llibrary
instructions.
Sessions
There is no support for sessions
Examples of Use
Hello World in C
Here is Hello World!
This source code block:
#+begin_src C :exports results printf ("Hello World!\n"); #+end_src
yields this result (type C-c C-c
in the source block):
Hello World!
Hello World in C++
std::cout<<"Hello World!\n";
This source code block:
#+begin_src C++ :includes <iostream> std::cout<<"Hello World!\n"; #+end_src
yields this result (type C-c C-c
in the source block):
Hello World!
Note that the <iostream>
used to be automatically #included, but now
it must be specified through the :includes
parameter.
Hello World in D
Here is Hello World!
This source code block:
#+begin_src D :exports results writefln ("Hello World!"); #+end_src
yields this result (type C-c C-c
in the source block):
Hello World!
Including multiple libraries
When several libraries need to be included, :includes
value should be set to a list:
#+begin_src C++ :includes '(<iostream> <stdio.h>) :results output std::cout<<"Hello World!\n"; printf("%d\n", 2+2); #+end_src
Hello World! 4
Note that:
- if no
main()
is declared, a trivial one is automatically provided, there is no directive like:
#include "stdio.h"
(in C)import std.stdio;
(in D)
because those libraries are so common that they are always included.
- C++ needs to explicitly include either
stdio.h
or<iostream>
Scalar variables
Variables may be declared outside the script. They are automatically inserted at the top of the script. Three types are supported, based on the look of the value:
string
orconst char*
int
double
Example in C or C++:
#+header: :var mystring="Sunday" :var myint=145 :var mydouble=3.14 #+BEGIN_SRC C printf ("mystring %s\n", mystring); printf ("myint %d\n", myint); printf ("mydouble %g\n", mydouble); #+END_SRC
yields this result (type C-c C-c
):
#+RESULTS: | mystring | Sunday | | myint | 145 | | mydouble | 3.14 |
Example in D:
#+header: :var mystring="Sunday" :var myint=145 :var mydouble=3.14 #+BEGIN_SRC D writefln ("mystring %s", mystring); writefln ("myint %d", myint); writefln ("mydouble %g", mydouble); #+END_SRC
yields this result (type C-c C-c
):
#+RESULTS: | mystring | Sunday | | myint | 145 | | mydouble | 3.14 |
If you want to see the expanded source code, without compiling and running it,
just type C-c C-v v
.
Process an Org Mode Table
How to handle a table
We take an Org mode table as input, process it, and output a new Org mode table.
This table will be input in the script, and iterated row by row:
#+name: somedata | nb | sqr | noise | |-------+-----+-------| | zero | 0 | 0.23 | | one | 1 | 1.31 | | two | 4 | 4.61 | | three | 9 | 9.05 | | four | 16 | 16.55 |
The table is converted to a variable in the script:
const char* somedata[5][3] = {...}; // in C & C++ string somedata[5][3] = [...]; // in D
The header, if any, is available to the script as well:
const char* somedata_header[3] = { "nb", "sqr", "noise" }; // in C & C++ string somedata_header[3] = [ "nb", "sqr", "noise" ]; // in D
The dimensions of the table are available:
int somedata_rows = 5; int somedata_cols = 3;
Additionally, an accessor function retrives a cell using the column name as found in the header:
const char* cell = somedata_h(3,"noise"); // "9.05" in C & C++ string cell = somedata_h(3,"noise"); // "9.05" in D
Type C-c C-v v
to look at the generate code without running it.
Note that table contents are (almost) always strings (as opposed to integers or floating point numbers). This allows to easily handle heterogeneous tables, and tables with missing values. To convert a string cell to a numeric value on the fly, use standard convertors:
int cell = atoi(somedata_h(4,"sqr")); // integer conversion in C & C++ double cell = atof(somedata_h(4,"noise")); // double conversion in C & C++ int cell = to!int(somedata_h(4,"sqr")); // integer conversion in D double cell = to!double(somedata_h(4,"noise")); // double conversion in D
Example in C & C++
This code:
#+name: c-table #+header: :exports results #+begin_src C++ :var somedata=somedata #include "stdlib.h" #include "stdio.h" int main() { for (int i=0; i<somedata_rows; i++) { printf ("%2d ", i); for (int j=1; j<somedata_cols; j++) { const char* cell = somedata[i][j]; printf ("%5s %5g ", cell, 1000*atof(cell)); } printf("\n"); } return 0; } #+end_src
yields this result:
#+RESULTS: c-table | 0 | zero | 0 | 0 | 0.23 | 230 | | 1 | one | 1 | 1000 | 1.31 | 1310 | | 2 | two | 4 | 4000 | 4.61 | 4610 | | 3 | three | 9 | 9000 | 9.05 | 9050 | | 4 | four | 16 | 16000 | 16.55 | 16550 |
Example in D
#+begin_src D :var somedata=somedata void main() { foreach (i, row; somedata) { writef ("%2s %7s ", i, somedata_h(i,"nb")); foreach (j, cell; row) if (j) // skip 1st column writef ("%5s %5s ", cell, 1000*to!double(cell)); writeln(); } } #+end_src
yields this result:
0 | zero | 0 | 0 | 0.23 | 230 |
1 | one | 1 | 1000 | 1.31 | 1310 |
2 | two | 4 | 4000 | 4.61 | 4610 |
3 | three | 9 | 9000 | 9.05 | 9050 |
4 | four | 16 | 16000 | 16.55 | 16550 |
Pure numeric table
This table is a pure numeric table.
3 | 3.3 |
4 | 4.1 |
5 | 5.9 |
6 | 6.5 |
In this special case, it is translated to a numeric table:
double MyTable[4][2] = { {3,3.3}, {4,4.1}, {5,5.9}, {6,6.5} };
If there is a blank cell among numeric cells, then the whole table falls back to the string case, where the blank cell is translated to the empty string "".
TODO Lists and vectors in the header
Shortcomings and known bugs
C++ vs. cpp
After the #+begin_src
block header, both C++
and cpp
are
accepted to specify C++ language.
However only C++
works for generated code visualization
through C-c C-v v
.
Pure numeric + header cast error
A type mismatch between strings and double cause an error when attempting to use the cell accessor with column name when the table is pure numeric.