Copyright © Quviq AB, 2017-2023
Version: 1.46.3
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.
In the third use case, there isn't anything gained by using eqc_cpp
,
one is just as well off using plain eqc_c
.
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>
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"]}]). ...
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/1For 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 seec_match_spec()
.
c_args_match_spec() = '_' | ['_' | string()]
Match method arguments, just '_' means any arity, otherwise the list of types must match.
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:
fun_info/0 | List C++ functions with their result types. |
fun_info/1 | Show the result type of a specific C++ function. |
running/0 | Check if the C/C++ binding is running. |
start/1 | Equivalent to start(CppModule, []). |
start/2 | Create a wrapper for and set up an interface to a C++ program/library/file. |
stop/0 | Stop the C++ wrapper. |
type_info/0 | List all defined types. |
type_info/1 | Show the type of the provided type defition. |
fun_info() -> any()
List C++ functions with their result types.
fun_info(Fun) -> any()
Show the result type of a specific C++ function.
running() -> any()
Check if the C/C++ binding is running
start(CppModule) -> any()
Equivalent to start(CppModule, []).
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()}
{swig_flags, string()}
{cxx_flags, string()}
{swig_file, string()}
{c_includes, [string()]}
{naming, [{Pattern::c_name_spec(), ErlName::atom() | string()}]}
{naming, {file, string()}}
show_wrapper_code
{additional_files, [string()]}
verbose
silent
{cflags, string()}
stop() -> any()
Stop the C++ wrapper.
type_info() -> any()
List all defined types.
type_info(Type) -> any()
Show the type of the provided type defition.
Generated by EDoc