Module eqc_cpp

This module provides functions for testing code written in C++.

Copyright © Quviq AB, 2017-2023

Version: 1.46.3

Description

This module provides functions for testing code written in C++. Interfacing C++ is done by creating a wrapper, adapting to C's calling convention and name mangling, and then using eqc_c.
Note: in order for QuickCheck to create the wrapper you must have SWIG installed, since it is used to parse and interpret C++ definitions.

Introduction

There are three main use cases:

In the third use case, there isn't anything gained by using eqc_cpp, one is just as well off using plain eqc_c.

Simple example

In the simple example we have only a .cpp file (and possibly a corresponding header file). If the file MyInt.cpp contains:
 class MyInt {
   public:
     int i;
     MyInt(): i(42) {};
     MyInt(int x): i(x) {};
     void inc();
     MyInt &operator++();
 };

 void MyInt::inc(){ i++; }
 MyInt &MyInt::operator++(){ i++; }

 void test(int x){
   MyInt i1, i2(x);
   i1.inc();
   ++i2;
 } 
Then it is enough to invoke eqc_cpp:start('MyInt') to automatically create a temporary SWIG file, produce a wrapper, compile it and load the C interface with eqc_c.
 104> eqc_cpp:start('MyInt').
 ok
 105> 'MyInt':
 'MyInt++'/1      'MyInt_get_i'/1  'MyInt_inc'/1    'MyInt_new'/0
 'MyInt_new'/1    'MyInt_set_i'/2  module_info/0    module_info/1
 test/1
 105> I1 = 'MyInt':'MyInt_new'(), 'MyInt':'MyInt++'(I1), 'MyInt':'MyInt_get_i'(I1).
 43
 106>

Normal use case

A more realistic use case is where you have a C++ library (compiled into object file(s)). In order to create a binding for testing it is then necessary to create a SWIG interface description. From this description QuickCheck will automatically create a wrapper module and a C API, and compile and load it with eqc_c. Two options should be given to start/2, 'swig_file' (the SWIG interface file) and 'additional_files' should list the object file(s) of the library. For example:

 117> eqc_cpp:start('CVector', [{swig_file, "CVector.swg"}, {additional_files, ["CVector.o"]}]).
 ...
 

Naming and function overloading

One notable difference between C and C++ is function overloading (a function with the same name but with different arity and/or different argument type(s)). By default (using the rename mechanism of eqc_c:start/2) all functions with the same name on the C++ side will be given the same name also in Erlang. In many cases (eqc_c does a good job disambiguating calls, but fails for example to distinguish int from long). In ambiguous cases it is necessary, or preferrable, to change the default, in yet other cases it can be convenient. User defined names are given by providing a 'naming' argument to start/2, for example:

 106> eqc_cpp:start('MyInt', [{naming, [{{"MyInt", "inc", '_'}, "just_inc"},
                                        {{"MyInt", new, ['_']}, "newMyInt1"},
                                        {{"test", '_'}, "test_it"}
                                       ]}]).
 ok
 107> 'MyInt':
 'MyInt++'/1      'MyInt_get_i'/1  'MyInt_new'/0    'MyInt_set_i'/2
 just_inc/1       module_info/0    module_info/1    newMyInt1/1
 test_it/1 
For a larger project it is also possible to give a file name with the (re-)naming. With the file MyInt_naming.eqc containing:
 {{"MyInt", "inc", '_'}, "just_inc"}.
 {{"MyInt", new, ['_']}, "newMyInt1"}.
 {{"test", '_'}, "test_it"}.
 
The following is equivalent to the example above.
 111> eqc_cpp:start('MyInt', [{naming, {file, "MyInt_naming.eqc"}}]).
 ok 

The renaming file format is a list of tuples, each tuple terminated by a dot (such that the Erlang library function file:consult/1 can parse it).

For additional examples see c_match_spec().

Data Types

c_args_match_spec()

c_args_match_spec() = '_' | ['_' | string()]

Match method arguments, just '_' means any arity, otherwise the list of types must match.

c_match_spec()

c_match_spec() = {string(), c_args_match_spec()} | {string(), string() | new | delete, c_args_match_spec()}

Matching C++ functions (and class members) in order to use user defined renaming.
Examples:

Function Index

fun_info/0List C++ functions with their result types.
fun_info/1Show the result type of a specific C++ function.
running/0Check if the C/C++ binding is running.
start/1Equivalent to start(CppModule, []).
start/2Create a wrapper for and set up an interface to a C++ program/library/file.
stop/0Stop the C++ wrapper.
type_info/0List all defined types.
type_info/1Show the type of the provided type defition.

Function Details

fun_info/0

fun_info() -> any()

List C++ functions with their result types.

fun_info/1

fun_info(Fun) -> any()

Show the result type of a specific C++ function.

running/0

running() -> any()

Check if the C/C++ binding is running

start/1

start(CppModule) -> any()

Equivalent to start(CppModule, []).

start/2

start(Module::atom(), Options::proplists:proplist()) -> ok | failed | {error, string()}

Create a wrapper for and set up an interface to a C++ program/library/file. It works on top of eqc_c, and as the last step eqc_c:start/2 is invoked. The interface is loaded as the Erlang module Module, and all options that are not used by start/2 are passed to eqc_c:start/2. The specific options for C++ are:

{swig, string()}
Specifies how to call SWIG (default: swig).
{swig_flags, string()}
Flags to pass to swig.
{cxx_flags, string()}
Flags to pass to C++ compiler when compiling the wrapper.
{swig_file, string()}
The path to the file containing the SWIG interface description.
{c_includes, [string()]}
List of filenames to #include in generated C wrapper code. This is needed if the C++ code uses defined C types such as size_t.
{naming, [{Pattern::c_name_spec(), ErlName::atom() | string()}]}
User defined renaming.
{naming, {file, string()}}
User defined renaming specified in file.
show_wrapper_code
Output the generated wrapper code, useful when something goes wrong.
Commonly used C options:
{additional_files, [string()]}
Additional files (C sources or C/C++ object files) to compile or link.
verbose
Print the commands used to build the C code.
silent
Don't print warnings and errors from the C compiler.
{cflags, string()}
Additional flags to the C compiler.

stop/0

stop() -> any()

Stop the C++ wrapper.

type_info/0

type_info() -> any()

List all defined types.

type_info/1

type_info(Type) -> any()

Show the type of the provided type defition.


Generated by EDoc