Struct Wrapping Example
Struct Wrapping Example
In some cases you may have a struct that is a simple container for data, and doesn’t have a constructor or destructor associated with it. In this case you can save yourself some work by defining the members of the struct. This will create a few default constructors for the wrapping class, and allow you to define functions using the struct as a class.
Consider the following C struct, which is a simple container for a set of statistics describing a soccer player:
struct player_stats {
int goals_scored;
int yellow_cards;
int red_cards;
};
We can create a PlayerStats class using the following description. Note the ‘members’ field in the equivalent-struct:
classes:
- name: "PlayerStats"
namespace: "soccer"
equivalent-struct:
name: "player_stats"
includes: "stats.h"
members:
- name: "goals_scored"
type: "int"
- name: "yellow_cards"
type: "int"
- name: "red_cards"
type: "int"
Note the members
field, which contains the description of the fields that
should be handled by the default constructors. The new class will have a simple
constructor with three parameters, each corresponding to the listed members.
There will also be two other constructors which accept either a struct, or a
struct pointer, and copy all members to the class instantiation.
This is all that’s required to generate the basic struct wrapping. However, if you’d like a default constructor that doesn’t require any parameters, then you’ll need to provide a little more information. For each member, just define a default value. This would look like this:
members:
- name: "goals_scored"
type: "int"
default-value: 0
- name: "yellow_cards"
type: "int"
default-value: 0
- name: "red_cards"
type: "int"
default-value: 0
Now it will be much easier to extend this class, as it provides a default constructor that can be called to initialize a child class. If you only provide a few default values but not all of them, those will be optional in the constructor.
Adding a function to our PlayerStats class is the same as with any other Wrapture class. For example, if we have a simple print function for the stats:
void print_player_stats( struct player_stats *stats );
Then we would provide the following function description to get a member
function called Print
:
functions:
- name: "Print"
wrapped-function:
name: "print_player_stats"
params:
- name: "equivalent-struct-pointer"
includes: "stats.h"
All of this results in a C++ class with the following signature.
namespace soccer {
class PlayerStats {
public:
struct player_stats equivalent;
PlayerStats( int goals_scored, int yellow_cards, int red_cards );
PlayerStats( struct player_stats equivalent );
PlayerStats( struct player_stats *equivalent );
void Print( void );
};
}
If you want to run this example, all that remains after using wrapture to
generate the sources is to compile the various sources and run the stats_usage
program to see the output:
# assuming that you're using sh and have g++
g++ -I . stats.c PlayerStats.cpp stats_usage.cpp -o stats_usage_example
./stats_usage_example
# output:
# default player's stats:
# player scored 0 goals, earned 0 yellow cards, and 0 red cards
# my player's stats:
# player scored 3 goals, earned 5 yellow cards, and 1 red cards
# their player's stats:
# player scored 0 goals, earned 4 yellow cards, and 4 red cards