C++ Automatically Exposing Class Members to Multiple APIs - c++

Short:
There are many clever libraries out there that allow you to expose a class' members for various purposes, such as serialisation, exposure to a lua environment, etc. The problem is that for each clever solution you have to register a class' stuff for each api, which results in a lot of work duplication and boilerplate.
What is a way that I can register a class and its members and methods ONCE with some kind of flags attached and get various autogenerated methods
Long:
Lets say I have a class:
class C {
public:
int i; // Some int
vec3 v; // Some non-POD value
int function(int foo, char bar) // Some function
int hidden; // Some internal stuff I don't want exposed
}
What I'd like to do is be able to mark various members and methods at declaration time to have them be put in the various boilerplate automatically:
So declaration might look like:
class C {
public:
LUAREG JSON BINSER int i; // Marks member "i" to be exposed to the lua enviroment,
// JSON serialisable, binary serialisable
JSON vec3 v; // Only exposed to JSON function
LUAREG void someFunction() {} // Marks this method to be exposed to the lua enviroment
}
Or perhaps writing one registration function that does all the declarations:
void C::register_class() {
registrator::register_class<C>("C")
.addData("i", &i, FLAG_LUA | FLAG_JSON | FLAG_BINARY_SERIALISABLE)
.addFunction("someFunction", &someFunction, FLAG_LUA)
.end_class()
}
(I've seen this pattern some times - does this have a name?)
I want to be able to automatically generate various boilerplate functions for said class. For example:
/// Adds all fields with FLAG_JSON to a "json" object to be later serialised
void toJson(const C & c, json & j) {
toJson(c.i, "i", j);
toJson(c.v, "v", j);
}
/// Binary seralises all members with flag FLAG_BINARY_SERIALISABLE and stores the result in s
void serialise(const C & c, string & s) {
serialise(c.i, s);
serialise(c.v, s);
}
/// Registers all stuff with flag FLAG_LUA to some lua environment
void register_lua(lua_State * const L) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x).comment("Some int") // generates documentation of "int x : Some int"
.addData("v", &C::v).comment("Some vector")
.addFunction("function", &C::function).comment("some function") // generates: "int function(int, char) : some function"
.endClass()
}
/// Register to some *other* lua environment (such as a read only context for rendering)
void register_lua_readonly(lua_State * const L2) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x, false).comment("Some int")
.endClass()
}
/// Generates some user readable breakdown of all members
string dump() {
...
}
Now you can see with many classes this will become very tedious, bloaty and error prone to do manually
What is the best way to approach this? I am tempted to use a macro to spit out the functions, but have no idea how to approach the registration stage. Cheers!

I have a solution for this - I rolled my own reflection library - https://github.com/SnapperTT/STTR
class C {
public:
int i;
double d;
int func(int z) const {
return z;
}
static int static_var;
static int static_func() { return 5; }
};
int C::static_var = 7;
struct D : public C {
int di;
};
int main(int argc, char ** argv) {
// Registration
sttr::RegNamespace mNamespace("testns");
mNamespace.beginClass<C>("C")
.regField(&C::i, "i")
.regField(&C::d, "d")
.setUserFlags(0x00F00BAA) // Sets the user flags for the last added item
.setUserString("You can use this for whatever")
.setUserData((void *) &someStruct)
.regField(&C::func, "func")
.regField(&C::static_var, "static_var")
.regField(&C::static_func, "static_func")
.endClass()
.findClass("C").beginClass<D>("D") // Class inherritance. Also you can just beginClass<D>("D") inside C
.regField(&D::di, "di")
.endClass();
}
The key to this solution is that I can attach flags to registered members (so LUA could be 1 << 0, JSON could be 1 << 1, etc.
Automatic json serialisation and lua registration is done via a visitor. The visitor checks if the members have the relevent flag and either does its thing or skips onto the next member.
I have also attempted to use RTTR: https://github.com/rttrorg/rttr - its a nice, if albeit bulky library. I rolled my own library because I didn't like the visitor interface and the voluminous template error messages.
Finally automatic documentation is done by running a script that does a bunch of regex find-and-substitutes to pick out cases of typename Foo; /// Some documentation and create a static const char * const docv_Foo = "Some documentation"; and registers it. This does add an intermediate step to compilation but its not at all bad.

Related

How to mock a function that takes an already defined lambda function and have coverage over lambda function

I am learning unit testing using googletest and am unsure how to cover a function.
In short, I need to get coverage over lambda function (lets say L), defined inside a mother function M. M calls a function C (defined in another file) that takes as argument lambda function L (a callback). I am writing a unit test for M, and need to call M, mocking the outside function M while also ensuring C is mocked and L is covered properly.
In short, object->M has L and M calls C(L).
Is there a way in google test to do this?
General shape of what I've already tried:
/* source code */
/* header */
struct Object
{/*struct methods*/
//M declaration
int M();
};
/* cpp file */
int M()
{
/* some operations */
auto L = [](int number){/* operations, returns 0; */};
int store; //storing the result of C
store = C(L);
}
/* other file */
int C(int* L(int))
{
/* some operations */
L(1);
return some_int;
}
Unit test file code:
#include <gmock/gmock.h>
#include <gtest.h>
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::DoAll;
using ::testing::SetArgReferee;
using ::testing::SetArgPointee;
using ::testing::SetArrayArgument;
using ::testing::_;
/* mock class*/
class MockedFunctions
{
public:
/* going to put 5 ints for the sake of the example */
MOCK_METHOD1(C, int(int));
};
class TestObject : public ::testing::Test
{
public:
TestObject(){}
~TestObject(){}
protected:
Object *objectInstance;
virtual void SetUp()
{ objectInstance = new Object;}
virtual void TearDown()
{ delete objectInstance;}
};
/* test for function */
TEST_F(TestObject, test_M)
{
MockedFunctions test_C;
EXPECT_CALL(test_C, C(_))
.Times(1)
/* don't care about passed number to L */
.WillOnce(DoALL (SetArgPointee<0>(L(3)), Return(0));
/* coud put EXPECT_EQ as well */
objectInstance->M();
}
This gives me an error at .WillOnce stating L was not declared in this scope.
Note that I do not care about the contents of L, as long as they are covered. What I have found so far regarding this topic suggested to mock my lambda function L, which I do not want to do here, since I need coverage over its code as part of function M.
While I am not required, in this case, to use strictly the GTest style (as my tutor did not know how to proceed with this L function coverage) and could use a stub for C that would force the usage of L (I have this version implemented at the moment to be able to compile with the rest of the code), is it nonetheless possible to obtain this coverage using strictly a googletest style?
Thanks!
Eventually found a solution and posting it for reference;
My solution was to find a way to store the callback method I was interested in inside a container, creating auxiliary methods for this and to obtain some output from that vector.
Inside the class containing the MOCK_METHODX() declarations, I first used a typedef to identify my function more easily.
Then, declared in a private block the vector and a void pointer which will be used to pass the function around.
Auxiliary methods to get contents at position x of the vector (I had cases where I would run my mocked function multiple times inside a test and thus wanted to see how each call performed), adding to vector, clearing contents (reset for other tests) and so forth.
Static pointer of type MockedFunctions used to provide an object to "resume" normal mock control behavior after our desired data has been extracted.
//inside my header file.
#include <gmock/gmock.h>
#include <vector>
class MockedFunctions {
public:
//lets say function L has params (int, void*)
typedef int (myCb) (int arg_from_cb_L, void* objptr_from_cb_L));
MockedFunctions(){}
virtual ~MockedFunctions(){}
//giving C more arguments than just the callback L
MOCK_METHOD2(C, int(int arg1, int(*L)(int, void*));
private:
//note due to namespace limitations, I'm including the std prefix
std::vector<myCb> callback_storage;
void *cb_obj_copy;
public:
/* Multiple public blocks just for readability purposes.
* Note the internal usage of vector methods.
*/
void cb_clear(){
if(callback_storage.empty())
{
callback_storage.clear();
}
}
void cb_add(myCb callback){
callback_storage.push_back(callback);
}
myCb* cb_result_at(int i){
return callback_storage.at(i);
}
//to store one of the params from the passed callback
void cb_copy_obj(void* obj){
cb_obj_cb = obj;
}
void cb_get_obj_copy(){
return cb_obj_copy;
}
};
class TestMethods : public ::testing::Test
{
public:
static std::unique_ptr<MockedMethods> testMockedMethods;
TestMethods(){
/* as we call other methods from MockedMethods apart from C,
* it would trigger warnings. Using NiceMock hides them for
* cleaner output.
*/
testMockedMethods.reset(new ::testing::NiceMock<MockedMethods>());
}
~TestMethods() override{
testMockedMethods.reset();
}
virtual void SetUp() override {}
virtual void TearDown() override {}
};
Now, inside my cpp file, I defined C and instantiated the pointer.
std::unique_ptr<MockedMethods> TestObject::testMockedMethods(new MockedMethods() );
int C ( int arg1, int(*L)(int arg1_cb, void* arg2_cb)){
TestMethods::testMockedMethods->cb_add(L);
TestMethods::testMockedMethods->cb_copy_obj(arg2_cb);
/* to avoid complications, took L's return type of int and put a 0
* directly, we don't care at this point since we will overload the
* method afterwards.
*/
return TestMethods::testMockedMethods->C(arg1, 0);
}
As for the actual testing, placed where you see fit:
class TestCaseClass : public TestMethods
{
public:
TestCaseClass(){}
~TestCaseClass(){}
protected:
//Here, object is the struct name mentioned previously in the question.
Object *instance;
// ...
virtual void SetUp()
{
instance = new Object();
// ...
}
virtual void TearDown()
{
delete instance;
}
};
TEST_F(TestCaseClass, test_M)
{
// testing method M from struct Object
/* Run tests normally on C, results will be stored. By our definition, a different object
* will be the one calling C, so pay attention to it.
*/
EXPECT_CALL(*testMockedMethods, C(_, _))
.Times(1)
.WillOnce(Return(1))
// I noticed at this point M above did not return anything, suppose it returns store
EXPECT_EQ(instance->M(), 1);
// Now to get coverage or data from our callback. First, get the method in cb_obj
MockedMethods::myObj* cb_method = testMockedMethods->cb_result_at(0);
// Now get one of its arguments, like that void*. Note we're using our get-ers
void* mock_object = testMockedMethods->cb_get_obj_copy();
/* And finally, call our method, finally getting coverage. You can pass
* various parameters for branching.
*/
cb_method(0, mock_object);
// Don't forget we clear the vector of contents in case we re-use it in another test.
testMockedMethods->cb_clear();
}
While not the most direct solution, it proved effective and I tried to include a few usage cases one might encounter in creating their tests.
Happy coding!

Binding C++ functions & calling Lua functions with class as parameter

I've been reading about Lua/C++ and I had a question about design I was hoping I could get some help on.
What I want:
I want so my class in C++ (Created and Destroyed by C++) to be able to call
a Lua function using itself as a parameter.
Eg.
object.h
class Object
{
public:
Object(const std::string & onLoad, const std::string & onEvent);
~Object();
void OnLoad();
void RegisterEvent(const std::string & eventID);
void OnEvent(const std::string & eventID);
void SetValue(int value);
private:
int m_value;
std::string m_onLoad;
std::string m_onEvent;
};
object.cpp
Object::Object(const std::string & onLoad, const std::string & onEvent)
: m_value(0)
, m_onLoad(onLoad)
, m_onEvent(onEvent)
{
}
Object::~Object()
{
GAME->GetEventManager()->UnregisterListener(this);
}
void Object::OnLoad()
{
//
// call lua function [name store in: m_onLoad]
// eg. m_onLoad = Object_OnLoad
// in lua ->
// function Object_OnLoad(object)
//
}
void Object::RegisterEvent(const std::string & eventID)
{
GAME->GetEventManager()->RegisterEvent(this, eventID);
}
void Object::OnEvent()
{
//
// call lua function [name store in: m_onEvent]
// eg. m_onEvent = Object_OnEvent
// in lua ->
// function Object_OnEvent(object, eventID)
//
}
void Object::SetValue(int value)
{
m_value = value;
}
script.lua
function Object_OnLoad(object)
object:RegisterEvent("EVENT_CURRENT_HEALTH_CHANGED")
end
function Object_OnEvent(object, eventID)
if (eventID == "EVENT_CURRENT_HEALTH_CHANGED")
object:SetValue(GetCurrentHealth());
end
test.cpp
Object *pTest = new Object("Object_OnLoad", "Object_OnEvent");
pTest->OnLoad();
GAME->GetEventManager()->TriggerEvent(CEvent("EVENT_CURRENT_HEALTH_CHANGED"));
delete pTest;
After Some reading:
From what I've read this is no direct way to assign C++ class instance functions.
Non-member functions are needed. Tables are used to track functions.
My Questions:
What do I push as an argument when calling the Lua functions (Object_OnEvent(object, eventID) etc...) Is it a pointer to the object
How does Lua know the object design
Do I need a table per object or instance
Do I need to duplicate all the functions I intend to use in Lua again as normal functions grabbing a the ptr to call it from
As a final and possible single question:
Is there any place I could get more information on what I'm trying to achieve described above.
I'm probably just going to go back to step one and try and absorb this information again.
I still wan't to make my post tho. I'll post back myself if I set it up.
There are many questions, but in principle, if I understand you correctly, you want to bind your C++ classes to Lua, have a shared object lifetime and automatic garbage collection, and be able to call Lua functions on objects created on the C++ side.
This is all possible with either low-level glue code, or dedicated binding libraries, such as LuaBridge and LuaState. LuaState is used in my answer for convenience and fast prototyping.
What's not yet clear is why you want to define a trivial function in Lua, such as Object_OnLoad to call it from C++, which would call a method of an object that you have created in the same scope on the C++ side. I'd guess, you have a more complicated picture in your code, so that such Lua usage pattern would be justified. In that case, one by one:
The ingredients
Binding a class to Lua
Here's a declarative binding that you can call once before calling any other Lua functions
void luabridge_bind(lua_State *L) {
luabridge::getGlobalNamespace(L)
.beginClass<MyObject>("MyObject")
.addConstructor<void(*)(), RefCountedPtr<MyObject> /* creation policy */ >()
.addFunction("RegisterEvent", &MyObject::RegisterEvent)
.endClass()
;
}
To perform the binding:
lua::State state;
luabridge_bind(state.getState());
Calling a lua function on a C++ side object
LuaState unfortunately cannot use objects in call parameters at the moment, while primitives work, i.e. from the readme:
state.doString("function add(x, y) return x + y end");
int result = state["add"](1,2);
But what one could do is to temporary create a global variable instance (watch out for name collisions) and call the function on it.
Preparing the script:
static const char *script =
"function Object_OnLoad(object)\n"
" object:RegisterEvent('EVENT_CURRENT_HEALTH_CHANGED')\n"
"end"
;
state.doString(script);
Creating an automatically lifetime-managed object:
auto my_obj = RefCountedPtr<MyObject>(new MyObject);
Calling the lua function on the object:
SetGlobal(state.getState(), "my_obj", my_obj);
state.doString("Object_OnLoad(my_obj); my_obj = nil");
Where SetGlobal can look like that:
template <typename T>
void SetGlobal(lua_State* L, const char *name, T value) {
luabridge::push(L, value);
lua_setglobal(L, name);
}
A complete example and comments
You can find the whole example code at Github: try_luabridge.cpp
which has been compiled and run at Travis CI.
The possibilities are limitless. It's up to you how you structure your code, so, naturally, this answer won't provide code that would immediately fit your needs. However, I'd encourage you to read Programming in Lua, and LuaBridge and LuaState manuals to get a better overview of the possiblities that are at your hand.

C++ : nameable objects belonging to an instance of a class, and stored in it

I am trying to make it possible for a programmer (who uses my library) to create nameable instances of type X that are stored inside an instance of class C (or at least are exclusive to that instance).
These are the only two (ugly) solutions I have managed to come up with (needless to say, I am just picking up C++)
1)
class C
{
public:
class XofC
{
public:
XofC() = delete;
XofC(C& mom)
{
mom.Xlist.emplace_front();
ref = Xlist.front();
}
X& access()
{
return ref;
}
private:
X& ref;
};
//etc
private:
std::forward_list<X> Xlist;
friend class XofC;
//etc
}
Problem:
Having to pass everywhere XofC instances.
2)
class C
{
public:
void newX(std::string);
X& getX(std::string);
//etc.
private:
/*possible run-time mapping implementation
std::vector<X> Xvec;
std::unordered_map<std::string, decltype(Xvec.size())> NameMap;
*/
//etc
}
Problem:
This does the job, but since all names of X (std::string) are known at compilation, the overhead of using run-time std::unordered_map<std::string, decltype(Xvec.size())> kind-of bugs me for something this simple.
Possible(?) solution: compile-time replacing of std::string with automatic index (int). Then I could use:
class C
{
public:
void newX(int); //int: unique index calculated at compile time from std::string
X& getX(int); //int: unique index calculated at compile time from std::string
//etc.
private:
std::vector<X> Xvec;
}
Questions:
Is there a 3)?
Is a compile time solution possible for 2)?
This is the real-life situation: I was starting my first C++ "project" and I thought I could use the practice and utility from an awesome user-friendly, simple and fast argument management library. I plan to make an ArgMan class which can parse the argV based on some specified switches. Switches would be named by the programmer descriptively and the trigger strings be specified (e.g. a switch named recurse could have "-r" and "-recursive" as triggers). When necessary, you should be easily able to get the setting of the switch. Implementation detail: ArgMan would have a std::unordered_map<std::string/*a trigger*/, ??/*something linking to the switch to set on*/>. This ensures an almost linear parse of argV relative to argC. How should I approach this?
You could 'abuse' non-type template arguments to get compiletime named instances:
Live on Coliru
Assume we have a data class X:
#include <string>
struct X
{
int has_some_properties;
std::string data;
};
Now, for our named instances, we define some name constants. The trick is, to give them external linkage, so we can use the address as a non-type template argument.
// define some character arrays **with external linkage**
namespace Names
{
extern const char Vanilla[] = "Vanilla";
extern const char Banana [] = "Banana";
extern const char Coconut[] = "Coconut";
extern const char Shoarma[] = "Shoarma";
}
Now, we make a NamedX wrapper that takes a const char* non-type template argument. The wrapper holds a static instance of X (the value).
// now we can "adorn" a `namedX` with the name constants (above)
template <const char* Name>
struct NamedX
{
static X value;
};
template <const char* Name> X NamedX<Name>::value;
Now you can use it like this:
int main()
{
X& vanilla = NamedX<Names::Vanilla>::value;
vanilla = { 42, "Woot!" };
return vanilla.has_some_properties;
}
Note that due to the fact that the template arguments are addresses, no actual string comparison is done. You cannot, e.g. use
X& vanilla = NamedX<"Vanilla">::value;
becuase "Vanilla" is a prvalue without external linkage. So, in fact you could do without some of the complexity and use tag structs instead: Live on Coliru
While Neil's solution did what I asked for, it was too gimmicky to use in my library. Also, sehe's trick is surely useful, but, if I understood correctly, but doesn't seem related to my question. I have decided to emulate the desired behavior using method 1), here is a less broken attempt at it:
class C
{
private:
class X
{
//std::string member;
//etc
};
public:
class XofC
{
public:
XofC(C & _mom) : mom(_mom)
{
mom.Xlist.emplace_front();
tehX = &(Xlist.front());
}
X & get(maybe)
{
if (&maybe != &mom) throw std::/*etc*/;
return &tehX;
}
private:
X * tehX;
C & mom;
};
private:
//etc
std::forward_list<X> Xlist;
friend class XofC;
//etc
};
Usage:
C foo;
bar = C::XofC(foo); //acts like an instance of X, but stored in C, but you have to use:
bar.get(foo)/*reference to the actual X*/.member = "_1_";
Of course, the downside is you have to make sure you pass bar everywhere you need it, but works decently.
This is how it looks like in my tiny argument manager library:
https://raw.github.com/vuplea/arg_manager.h/master/arg_manager.h

Nested Classes C++ static inner methods (Xml parsing and trying to populate vector with values)

So this is what I am trying to accomplish. I am trying to use a sax parser to parse some XML. it looks like I need to call all their methods as statics. So if I want to pass a value back from say startElement it is static void startElement. Which brings me to my example code. I have been pulling my hair on how to update a value in a Nesting class from a static member function.
I have looked at several things such as defining OuterClass * oc; then trying to reference oc->allRecords, but since it is a static method inside, it fails. I am sure I am doing something wrong architecturally, so any feedback on what would be the right way to do this would be a great help. Thanks.
class Attribute {
string AttributeName;
string AttributeValue;
};
typedef shared_ptr<Attribute> AttributePtr;
class AttributeSet {
vector<AttributePtr> Attributes;
};
typedef shared_ptr<AttributeSet> AttributeSetPtr;
class OuterClass {
public :
vector<AttributeSetPtr> allRecords;
class InnerClass {
public:
static mymethod1() {
// I need to be able to set attributes here :
// This would be the characters method for sax parsing
// What is the right way to Attributes.push_back(new Attribute(Name,Value));
}
static mymethod2() {
// I also need to be able to add Records here :
// This would be the endElement for sax parsing
// What is the right way to allRecords.push_back(AttributeSet);
}
};
// EDIT: CALLING CODE GOES HERE (WAS EDITED - SEE BELOW)
};
// ADDING INFORMATION REGARDING HOW METHOD 1 & 2 are called
xmlSAXHandler saxHandler;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.initialized = XML_SAX2_MAGIC;
...
saxHandler.endElementsNs = &InnerClass::method2;
saxHandler.characters = &InnerClass::method1;
...
InnerClass innerXmlParsingClass
xmlSaxUserParseMemory( &saxHandler, &innerXmlParsingClass, xmlString, xmlString.length());
Your mistake is using an inner class (are you coming from Java?).
I don't know what you believe you are are achieving with an inner class, but it won't work. Don't use inner classes in C++ unless you really know what it does (for inner classes, protected and private members of the outer classes are seen as if they were public).
Now, as the solution to your problem, I guess it depends on the implementation you're using (I used once Apache's Xerces SAX, but I know Microsoft offers its own SAX implementation, and that there should be a lot other alternatives, so...)
Edit
After the comment, I found the following tutorial:
http://www.jamesh.id.au/articles/libxml-sax/libxml-sax.html
I must say that, coming from Java to C++, and using a C API, you have a kind of courage...
:-D
If you are not familiar enough with function pointers, and C in general, using libxml2 will be a challenge. Be sure that in the end, you will understand those notions... Note that C have a way to handle the data that C++, Java or C# developers associate to this. The C way is to pass a pointer to your data (the user data) to a function, and when the callback is called, it passes back this pointer, typed as a void *. You must then cast it back to its right type, and voilà, you have your this back.
:-)
Anyway, reading the doc, I see that when you parse the file, you'll call the following C function:
int xmlSAXUserParseFile( xmlSAXHandlerPtr sax,
void * user_data,
const char * filename);
the user_data part is the one that interest you because it enables you to have a context. So, wrapping this function in a C++ class, you could have something like:
// MySaxBase.hpp
class MySaxBase
{
public :
MySaxBase() ;
int parseFile(const std::string & p_filename) ;
virtual void startDocument() ;
virtual void endDocument() ;
private :
static void do_startDocument(void *p_user_data) ;
static void do_endDocument(void *p_user_data) ;
xmlSAXHandler m_sax ;
}
.
// MySaxBase.cpp
extern "C"
{
void do_startDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->startDocument() ;
}
void do_endDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->endDocument() ;
}
} // extern "C"
MySaxBase::MySaxBase()
{
// the m_sax structure must be set to zero to NULL all its
// pointers to functions
memset(&m_sax, 0, sizeof(xmlSAXHandler)) ;
// Now, we initialize some pointers to the static method we
// want to be called
this->m_sax.startDocument = do_startDocument ;
this->m_sax.endDocument = do_endDocument ;
}
int MySaxBase::parseFile(const std::string & p_filename)
{
// the important thing, here, is the this pointer, passed as
// a user_data parameter
return xmlSAXUserParseFile(&m_sax, this, p_filename.c_str()) ;
}
void MySaxBase::startDocument()
{
// The document started. Override this method to
// actually do something
}
void MySaxBase::endDocument()
{
// The document ended. Override this method to
// actually do something
}
I did not test this, and I never used libxml2, but I guess the code must be Ok, and this should be enough for you to continue on your own: Just add the methods you want to support, initialize the sax handler with the relevant function pointers, and you'll have your class complete.
The MySaxBase::startDocument and MySaxBase::endDocument methods are virtual just for you to derive from MySaxBase and then override those methods.
Edit 2
I'll reproduce here Steve Jessop's excellent comment:
+1. One tiny quibble - I don't think that static member functions are guaranteed by the C++ standard to have C linkage / calling convention, but to use them as a callback from a C API, that's what they need. I don't specifically know what implementations it makes a difference, but for safety do_startDocument should be a free function declared with extern "C". On the same subject: a Java programmer may not realise you have make sure that the function can't throw an exception (because C doesn't have them). So you'd normally want to see a try/catch(...) in the wrapper function. – Steve Jessop
Following this, and after reading Johannes Schaub - litb (who else?) no less excellent answer at static vs extern "C"/"C++" , I modified the code to make do_startDocument and do_endDocument real C functions (i.e. wrapped in an extern "C" block). This usually is not important (I never encountered this kind of problem), but, better safe than sorry.
Your basic problem is that static methods are not per-instance, so there is no this pointer. You somehow need to get a OuterClass* passed to mymethod1 and mymethod2.
If you show us how mymethod1 and mymethod2 are called, we can help you further.
If it's simply called by you someplace where you have a OuterClass object, then your solution is simple:
class OuterClass
{
// ...
static void mymethod1(OuterClass* oc)
{
oc->all_records.push_back( something );
}
};
void some_func()
{
OuterClass oc;
OuterClass::method1(&oc);
}
Since you updated your question here is how you should do this:
class OuterClass {
public:
vector<AttributeSetPtr> allRecords;
void characters(const xmlChar* ch, int len)
{
// do here whatever you want
allRecords.push_back(bla bla);
}
static void static_characters(void* ctx, const xmlChar* ch, int len) {
// retrieve this pointer from ctx
static_cast<OuterClass*>(ctx)->characters(ch, len);
}
};
saxHandler.characters = &OuterClass::static_characters;
...
OuterClass outerClass;
xmlSaxUserParseMemory(&saxHandler, static_cast<void*>(&outerClass), xmlString, xmlString.length());

C++ Code Generation

In my epic quest of making C++ do things it shouldn't, I am trying to put together a compile time generated class.
Based on a preprocessor definition, such as (rough concept)
CLASS_BEGIN(Name)
RECORD(xyz)
RECORD(abc)
RECORD_GROUP(GroupName)
RECORD_GROUP_RECORD(foo)
RECORD_GROUP_RECORD(bar)
END_RECORDGROUP
END_CLASS
While I am fairly sure I generate a class that reads the data from the file system using this sort of structure (Maybe even doing it using Template Metaprogramming), I don't see how I can generate both the functions to access the data and the function to read the data.
I would want to end up with a class something like this
class Name{
public:
xyz_type getxyz();
void setxyz(xyz_type v);
//etc
list<group_type> getGroupName();
//etc
void readData(filesystem){
//read xyz
//read abc
//etc
}
};
Does anyone have any idea if this is even possible?
--EDIT--
To clarify the intended usage for this. I have files in a standard format I want to read. The format is defined already, so it is not open to change. Each file can contain any number records, each of which can contain any number sub records.
The numerous record types each contain a diffrent set of sub records, but they can be are defined. So for example the Heightmap record must contain a Heightmap, but can optional contain normals.
So I would want to define a Record for that like so:
CLASS_BEGIN(Heightmap)
RECORD(VHDT, Heightmap, std::string) //Subrecord Name, Readable Name, Type
RECORD_OPTIONAL(VNML, Normals, std::string)
END_CLASS
For which I would want to output something with the functionality of a class like this:
class Heightmap{
public:
std::string getHeightmap(){
return mHeightmap->get<std::string>();
}
void setHeightmap(std::string v){
mHeight->set<std::string>(v);
}
bool hasNormal(){
return mNormal != 0;
}
//getter and setter functions for normals go here
private:
void read(Record* r){
mHeightmap = r->getFirst(VHDT);
mNormal = r->getFirst(VNML);
}
SubRecord* mHeightmap, mNormal;
}
The issue I am having is that I need every preprocessor definition twice. Once for defining the function definition within the class, and once for creating the read function. As the preprocessor is purely functional, I cannot push the data to a queue and generate the class on the END_CLASS marco definition.
I cannot see a way around this issue, but wondered if anyone who has a greater understanding of C++ did.
If you are looking for a way to serialize/deserialize data with C++ code generation, I would look at Google protobufs (http://code.google.com/p/protobuf/) or Facebook's Thrift (http://incubator.apache.org/thrift/).
For protobufs, you write a data definition like so:
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
A Person C++ class is then generated that lets you load, save and access this data. You can also generate python, java, etc.
You might be able to solve this problem using boost tuples. It will result in a design which is different to what you are thinking of now, but it should allow you to solve the problem in a generic way.
The following example defines a record of the form "std::string,bool" and then reads that data in from a stream.
#include "boost/tuple/tuple.hpp"
#include <iostream>
#include <sstream>
using namespace ::boost::tuples;
The functions are used to read the data from an istream. The first overload stops the iteration through the tuple after we reach the last record type:
//
// This is needed to stop when we have no more fields
void read_tuple (std::istream & is, boost::tuples::null_type )
{
}
template <typename TupleType>
void read_tuple (std::istream & is, TupleType & tuple)
{
is >> tuple.template get_head ();
read_tuple (is, tuple.template get_tail ());
}
The following class implements the getter member for our Record. Using the RecordKind as our key we get the specific member that we're interested in.
template <typename TupleType>
class Record
{
private:
TupleType m_tuple;
public:
//
// For a given member - get the value
template <unsigned int MBR>
typename element <MBR, TupleType>::type & getMember ()
{
return m_tuple.template get<MBR> ();
}
friend std::istream & operator>> (std::istream & is
, Record<TupleType> & record)
{
read_tuple (is, record.m_tuple);
}
};
The next type is the meta description for our record. The enumeration gives us a symbolic name that we can use to access the members, ie. the field names. The tuple then defines the types of those fields:
struct HeightMap
{
enum RecordKind
{
VHDT
, VNML
};
typedef boost::tuple < std::string
, bool
> TupleType;
};
Finally, we construct a record and read in some data from a stream:
int main ()
{
Record<HeightMap::TupleType> heightMap;
std::istringstream iss ( "Hello 1" );
iss >> heightMap;
std::string s = heightMap.getMember < HeightMap::VHDT > ();
std::cout << "Value of s: " << s << std::endl;
bool b = heightMap.getMember < HeightMap::VNML > ();
std::cout << "Value of b: " << b << std::endl;
}
And as this is all template code, you should be able to have records nested in records.
This is a technique I use a lot in C and C++, called "list macro". Suppose you have a list of things like variables, error messages, interpreter opcodes, or anything about which repetitive code needs to be written. In your case it is class member variables.
Suppose it is variables. Put them in a list macro like this:
#define MYVARS \
DEFVAR(int, a, 6) \
DEFVAR(double, b, 37.3) \
DEFARR(char, cc, 512) \
To declare the variables, do this:
#define DEFVAR(typ,nam,inival) typ nam = inival;
#define DEFARR(typ,nam,len) typ nam[len];
MYVARS
#undef DEFVAR
#undef DEFARR
Now you can generate any sort of repetitive code just by redefining DEFVAR and DEFARR, and instantiating MYVARS.
Some people find this rather jarring, but I think it's a perfectly good way to use the preprocessor as a code generator, and accomplish DRY. And, the list macro itself becomes a mini-DSL.
I might play around with a record mixin to do something similar -- add functionality to a class automagically at compile time
template<class Base, class XyzRecType>
class CRecord : public Base
{
protected:
RecType xyz;
public:
CRecord() : Base() {}
RecType Get() {return xyz;}
void Set(const RecType& anXyz) {xyz = anXyz;}
void ReadFromStream( std::istream& input)
{
...
}
};
class CMyClass
{
};
int main()
{
// now thanks to the magic of inheritance, my class has added methods!
CRecord<CMyClass, std::string> myClassWithAStringRecord;
myClassWithAStringRecord.Set("Hello");
}
In general you can accomplish exactly what you want if you merge everything into one macro and then leverage Booost Preprocessor library to define your class. Look at how I implemented the MACE_REFLECT macro which does a partial specialization of an entire class and must reference each name twice in different parts.
This is very similar to how I automatically parse JSON into structs with the help of the pre-processor.
Given your example, I would translate it as such:
struct Name {
xyz_type xyz;
abc_type abc;
boost::optional<foo_type> foo;
boost::optional<bar_type> bar;
};
MACE_REFLECT( Name, (xyz)(abc)(foo)(bar) )
I can now 'visit' the members of Name from my parser:
struct visitor {
template<typename T, T p>
inline void operator()( const char* name )const {
std::cout << name << " = " << c.*p;
}
Name c;
};
mace::reflect::reflector<Name>::visit(visitor());
If your objects can be represented as structs, arrays, key-value-pairs and primitives, then this technique works wonders and gives me instant serialization/deserializtion to/from json/xml or your custom record format.
https://github.com/bytemaster/mace/blob/master/libs/rpc/examples/jsonv.cpp
I'm not exactly sure what you're looking for in some cases.
What happens to foo and bar in the specification?
What does getGroupName actually return? (foo,bar)? or GroupName?
It looks like you're trying to create a mechanism for loading and accessing on-disk structures of arbitrary layout. Is this accurate? (Edit: Just noticed the "set" member function... so I guess you're looking for full serialization)
If you're on a *nix system, specifying your own compiler to compile to .o (likely a perl/python/what-have-you script that finishes with a call to gcc) in the Makefile is a trivial solution. Others might know of ways of doing this on windows.