UP | HOME

Support via Liberapay

C, C++, D Source Code Blocks in Org Mode

Org Mode support for
C, C++
D

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

  1. 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 and g++. But others are usable as well.
    • For D, look at http://dlang.org/ for downloading and instructions. The compilers are called dmd and rdmd.

    Eventually, the compilers must be in the PATH.

  2. 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)

  3. 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 or const 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.

Documentation from the orgmode.org/worg/ website (either in its HTML format or in its Org format) is licensed under the GNU Free Documentation License version 1.3 or later. The code examples and css stylesheets are licensed under the GNU General Public License v3 or later.