I've been trying to figure out how to expose a property in my class that is a boost::tuple. The tuple is defined as follows:
typedef boost::shared_ptr<Action> action_ptr;
typedef boost::tuple<BattleCharacter*, action_ptr > ActionTargetTuple;
It's contained with a class defined as follows:
class Action : public Cloneable<Action>
{
public:
//Irrelevant Code Omitted
std::vector<ActionTargetTuple> Targets;
}
I've seen numerous articles while I was searching about how to convert a boost::tuple into a python tuple, but that's not what I'm looking to do. I want to be able to access the tuple as it exists on the Action class. (I know how to do the vector part).
class_<Action, std::auto_ptr<ActionWrapper> >("Action")
.def("Targets", &Action::Targets)
;
I expose it simply as above. I figured I might be able to expose it by some variation on the below:
class_<ActionTargetTuple>("ActionTargetTuple")
.def("get", &ActionTargetTuple::get<int>, return_value_policy<reference_existing_object>())
;
then use get from python, but if it is doable in this way, I'm not sure what the set up needs to be. Does anyone know how to do this/could suggest an alternative?
Thanks
You can use:
...
.add_property("Targets", & ActionTargetTuple::get, &ActionTargetTuple::set)
to make a read-write property using getter/setter methods in c++
If you want to control ownership:
namespace bp = boost::python;
...
.add_property("Targets",
bp::make_function(&ActionTargetTuple::get, bp::return_value_policy<...>()),
bp::make_function(&ActionTargetTuple::set, bp::return_value_policy<...>())
)
Besides using add_property as explained in the previous answer, and writing accessor functions, you can consider writing converters for your tuple (between boost::tuple and boost::python::tuple) and exposing those attributes directly with def_readonly or def_readwrite. It is worth it if you have many such attributes to expose.
This has a template you adapt can for c++→python conversion (use boost::tuple instead of std::pair), though unless you go c++0x, you have to write out templates for different number of arguments.
If your property is read-write, additionaly define from-python converter, you find examples on the web. Here is my code I use to define generic sequence-std::vector converter. In your case, you have to check that the python object is a sequence, that it has the right number of items, that you can extract required types from each of them; and then return new boost::tuple object.
HTH, edx.
P.S. I found ackward has the converters ready, perhaps you could just reuse it. Doc here
Related
I am somewhat familiar with type safety, and have used it successfully before in methods which receive several parameters of the same type (bool) to avoid confusion. For example:
// Old version of the method
void sendPackage(bool sendImmediately, bool dividePacket);
// Type safe version
enum SendImmediatelyPreference
{
SEND_IMMEDIATELY,
DO_NOT_SEND_IMMEDIATELY
};
enum PacketDivisionPreference
{
DIVIDE_PACKET,
DO_NOT_DIVIDE_PACKET
};
void sendPackage(
SendImmediateltPreference immediatePref,
PacketDivisionPreference divisionPref);
So the cryptic sendPackage(true, false) becomes sendPackage(SEND_IMMEDIATELY, DO_NOT_DIVIDE_PACKET).
The problem is that this is only an option for bool. I have a method that accepts several std::vector<std::string> and I'd like to minimise the posibility of the user inputting the arguments in the wrong order.
I can think of creating different classes which contains an std::vector<std::string> and either override tons of the std::vector methods or expose the internal vector.
Is there an easier way, some sort of typedef which enforces type safety? Using boost would be okay.
How about an alternative approach using named parameters? There are several ways of going about this in C++ described here. The tag approach using a tuple looks reasonable. There is also boost parameter.
This doesn't offer strong type safety, but you could argue that the user is just as likely to call the wrong constructor to make their type safe object as they are to use the wrong tag when calling your function. This situation is less likely to occur if the types are used throughout your application vs defined only for one particular function.
See also the discussion of boost strong typedef vs parameter for a similar purpose here.
Not sure I understood you correctly, but maybe this can help:
enum SendImmediatelyPreference : bool // allows only 2 options:
{
DO_NOT_SEND_IMMEDIATELY, // false
SEND_IMMEDIATELY // true
}
What about creating a class that inherits (public) from std::vector to have a strong typecheck. The advantage is that you only need to rewrite constructors..
You can also regroup your parameters in a std::unordered_map>, to implement argument as a dict (like in python, or javascript)
BOOST_STRONG_TYPEDEF is precisely a typedef which enforces type safety.
However, this answer provides some caveats related to using this strong typedef for just a function, and argues that the types should be used all over the code to prevent unnecessary castings.
I like to bundle the parameters in a config class or struct. For example:
struct SendOptions
{
bool send_immediately = false;
bool divide_packet = false;
// ...
};
void sendPackage(SendOptions options);
This has the additional advantage the extra options can be added later without needing to change the interface of sendPackage(SendOptions).
This does not increase type safety but it does help to prevent errors (especially if there are a lot of parameters), which is probably the goal you're trying to achieve.
What would be the best representation of a C/C++ function pointer (fp) in an UML structural diagram?
I'm thinking about using an interface element, may be even if 'degenerate' with the constraint of having at most a single operation declared.
I found some proposal in this document: C and UML Synchronization User Guide, Section 5.7.4. But this sounds quite cumbersome and not very useful in practice. Even if right from a very low level of semantic view. Here's a diagram showing their concept briefly:
IMHO in C and C++ function pointers are used as such a narrowed view of an interface which only provides a single function and it's signature. In C fp's would be used also to implement more complex interfaces declaring a struct containing a set of function pointers.
I think I can even manage to get my particular UML tool (Enterprise Architect) to forward generate the correct code, and synchronizing with code changes without harm.
My questions are:
Would declaration of fp's as part of interface elements in UML proivde a correct semantic view?
What kind of stereotype should be used for single fp declaration? At least I need to provide a typedef in code so this would be my guts choice.(I found this stereotype is proprietary for Enterprise Architect) and I need to define an appropriate stereotype to get the code generation adapted. Actually I have chosen the stereotype name 'delegate', does this have any implications or semantic collisions?
As for C++, would be nesting a 'delegate' sterotyped interface with in a class element enough to express a class member function pointer correctly?
Here's a sample diagram of my thoughts for C language representation:
This is the C code that should be generated from the above model:
struct Interface1;
typedef int (*CallbackFunc)(struct Interface1*);
typedef struct Interface1
{
typedef void (*func1Ptr)(struct Interface1*, int, char*);
typedef int (*func2Ptr)(struct Interface1*, char*);
typedef int (*func3Ptr)(struct Interface1*, CallbackFunc);
func1Ptr func1;
func2Ptr func2;
func3Ptr func3;
void* instance;
};
/* The following extern declarations are only dummies to satisfy code
* reverse engineering, and never should be called.
*/
extern void func1(struct Interface1* self, int p1, char* p2) = 0;
extern int func2(struct Interface1* self, char*) = 0;
extern int func3(struct Interface1* self, CallbackFunc p1) = 0;
EDIT:
The whole problem boils down what would be the best way with the UML tool at hand and its specific code engineering capabilities. Thus I have added the enterprise-architect tag.
EA's help file has the following to say on the subject of function pointers:
When importing C++ source code, Enterprise Architect ignores function pointer declarations. To import them into your model you could create a typedef to define a function pointer type, then declare function pointers using that type. Function pointers declared in this way are imported as attributes of the function pointer type.
Note "could." This is from the C++ section, the C section doesn't mention function pointers at all. So they're not well supported, which in turn is of course due to the gap between the modelling and programming communities: non-trivial language concepts are simply not supported in UML, so any solution will by necessity be tool-specific.
My suggestion is a bit involved and it's a little bit hacky, but I think it should work pretty well.
Because in UML operations are not first-class and cannot be used as data types, my response is to create first-class entities for them - in other words, define function pointer types as classes.
These classes will serve two purposes: the class name will reflect the function's type signature so as to make it look familiar to the programmer in the diagrams, while a set of tagged values will represent the actual parameter and return types for use in code generation.
0) You may want to set up an MDG Technology for steps 1-4.
1) Define a tagged value type "retval" with the Detail "Type=RefGUID;Values=Class;"
2) Define a further set of tagged value types with the same Detail named "par1", "par2" and so on.
3) Define a profile with a Class stereotype "funptr" containing a "retval" tagged value (but no "par" tags).
4) Modify the code generation scripts Attribute Declaration and Parameter to retrieve the "retval" (always) and "par1" - "parN" (where defined) and generate correct syntax for them. This will be the tricky bit and I haven't actually done this. I think it can be done without too much effort, but you'll have to try it. You should also make sure that no code is generated for "funptr" class definitions as they represent anonymous types, not typedefs.
5) In your target project, define a set of classes to represent the primitive C types.
With this, you can define a function pointer type as a «funptr» class with a name like "long(*)(char)" for a function that takes a char and returns a long.
In the "retval" tag, select the "long" class you defined in step 4.
Add the "par1" tag manually, and select the "char" class as above.
You can now use this class as the type of an attribute or parameter, or anywhere else where EA allows a class reference (such as in the "par1" tag of a different «funptr» class; this allows you to easily create pointer types for functions where one of the parameters is itself of a function pointer type).
The hackiest bit here is the numbered "par1" - "parN" tags. While it is possible in EA to define several tags with the same name (you may have to change the tagged value window options to see them), I don't think you could retrieve the different values in the code generation script (and even if you could I don't think the order would necessarily be preserved, and parameter order is important in C). So you'd need to decide the maximum number of parameters beforehand. Not a huge problem in practice; setting up say 20 parameters should be plenty.
This method is of no help for reverse engineering, as EA 9 does not allow you to customize the reverse-engineering process. However, the upcoming EA 10 (currently in RC 1) will allow this, although I haven't looked at it myself so I don't know what form this will take.
Defining of function pointers is out of scope of UML specification. What is more, it is language-specific feature that is not supported by many UML modeling software. So I think that the general answer to your first question suggests avoiding of this feature. Tricks you provided are relevant to Enterprise Architect only and are not compatible with other UML modeling tools. Here is how function pointers is supported in some other UML software:
MagicDraw UML uses <<C++FunctionPtr>> stereotypes for FP class members and <<C++FunctionSignature>> for function prototype.
Sample of code (taken from official site -- see "Modeling typedef and function pointer for C++ code generation" viewlet):
class Pointer
{
void (f*) ( int i );
}
Corresponding UML model:
Objecteering defines FP attributes with corresponding C++ TypeExpr note.
Rational Software Architect from IBM doesn't support function pointers. User might add them to generated code in user-defined sections that are leaved untouched during code->UML and UML->code transformations.
Seems correct to me. I'm not sure you should dive into the low-level details of descripting the type and relation of your single function pointer. I usually find that description an interface is enough detalization without the need to decompose the internal elements of it.
I think you could virtually wrap the function pointer with a class. I think UML has not to be blueprint level to the code, documenting the concept is more important.
My feeling is that you desire to map UML interfaces to the struct-with-function-pointers C idiom.
Interface1 is the important element in your model. Declaring function pointer object types all over the place will make your diagrams illegible.
Enterprise Architect allows you to specify your own code generators. Look for the Code Template Framework. You should be able to modify the preexisting code generator for C with the aid of a new stereotype or two.
I have been able to get something sort of working with Enterprise Architect. Its a bit of a hacky solution, but it meets my needs. What I did:
Create a new class stereotype named FuncPtr. I followed the guide here: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html
When I did this I made a new view for the profile. So I can keep it contained outside of my main project.
Modified the Class code templates. Basically selecting the C language and start with the Class Template and hit the 'Add New Stereotype Override' and add in FuncPtr as a new override.
Add in the following code to that new template:
%PI="\n"%
%ClassNotes%
typedef %classTag:"returnType"% (*%className%)(
%list="Attribute" #separator=",\n" #indent=" "%
);
Modified the Attribute Declaration code template. Same way as before, adding in a new Stereotype
Add in the following code to the new template:
%PI=""% %attConst=="T" ? "const" : ""%
%attType%
%attContainment=="By Reference" ? "*" : ""%
%attName%
That's all that I had to do to get function pointers in place in Enterprise Architect. When I want to define a function pointer I just:
Create a regular class
Add in the tag 'returnType' with the type of return I want
Add in attributes for the parameters.
This way it'll create a new type that can be included as attributes or parameters in other classes (structures), and operators. I didn't make it an operator itself because then it wouldn't have been referenced inside the tool as a type you can select.
So its a bit hacky, using special stereotyped classes as typedefs to function pointers.
Like your first example I would use a Classifier but hide it away in a profile. I think they've included it for clarity of the explaining the concept; but in practice the whole idea of stereotypes is abstract away details into profiles to avoid the 'noise' problem. EA is pretty good for handling Profiles.
Where I differ from your first example is that I would Classify the Primitive Type Stereotype not the Data Type stereotype. Data Type is a Domain scope object, while Primitive Type is an atomic element with semantics defined out side the scope of UML. That is not to say you cannot add notes, especially in the profile or give it a very clear stereotype name like functionPointer.
I had a question about boost python. I've been working on exporting some functionality of a project into boost python, and I haven't found a way to solve the following problem:
I have a set of StatusEffect objects that i store and use throughout the game. At the game startup, I want to be able to call a python script that will populate/add to the set of status effect objects. I'm having no problems exposing the StatusEffect class and it's derived class to python and calling the script.
The problem is that I'm storing that StatusEffect objects in an std::vector<boost::shared_ptr<StatusEffect> > Effects;
I have no idea how to create new instances of boost::shared_ptr<StatusEffect> aside from the method of adding a static create method as described here http://wiki.python.org/moin/boost.python/PointersAndSmartPointers Given the large number of constructors and the wide variety of derived classes I have, this seems an unoptimal solution at best. I'd like to be able to create instances of boost::shared_ptr directly using the constructors of the StatusEffect objects, and be able to add those to the vector. Is this possible?
An answer or some helpful suggestions would be helpful. I asked a simialr question yesterday but unfortunately it wasn't of much help.
Thanks in advance
I hope I am understanding your question. If you declare your python class with the shared_ptr as shown at http://wiki.python.org/moin/boost.python/PointersAndSmartPointers, then boost::python will automatically convert StatusEffect objects you create in python to shared_ptr<StatusEffect> if necessary (you can try this e.g. by .def-ing a function which takes const shared_ptr<StatusEffect>& or shared_ptr<StatusEffect> as argument, and call it with StatusEffect instance created in python.
If you want to assign an attribute of type vector<shared_ptr<StatusEffect> >, you must create converters for it (from python sequences, and back), that's described in documentation. For an example, see c++ to python converter template (line 120), python to c++ template (line 127), and then using it for various types (including shared_ptr's) contained in the sequences (line 212).
Then you can write something like yourObject.listOfStatusEffects=[StatusEffect(),StatusEffect(),StatusEffect()]
I am trying to make a toy language in c++. I have used boost spirit for the grammar, and hopefully for parser/lexer. The idea is a toy language where 'everything is an object' like javascript and some implementation of prototype based inheritance. I want to know how to implement the 'object' type for the language in c++. I saw source codes of engine spidermonkey but mostly it is done using structures, also getting more complex at later stages. As structures are more or less equivalent to classes in C++, I hope I could manage with the stdlib itself. All I want is a solid idea of how the basic object has to be implemented and how properties are created/modified/destroyed. I tried to take a look at V8, but its really confusing me a lot!
Have each class have pointers to parent classes and implement properties and methods in STL containers like <string,pointer_fun> so that you can add/remove dynamically methods.
Then you could just lookup a method in an obj, if there isn't then follow the ptr to parent and lookup there till you find one or fail non-existant method.
For properties you could have a template to wrap them in the STL container so that they share a common ancestor and you can store pointers like <string,property<type>* > where property makes created type inherit from common type.
With this approach and some runtime checks you can support dynamically anything, just need to have clear which are the lookup rules for a method when you call it in an object.
So essentially every obj instance in your system could be:
class obj{
type_class parent*;
string type;
std::map<string,pointer_fun> methods;
std::map<string,property_parent_class> properties;
}
And have constructors/destructor be normal methods with special names.
Then in obj creation you could just lookup for type_name in type_objs and copy the member and properties from the type to the impl obj.
EDIT:
About function objects, you can use functors inheriting from a common one to use the container_of_pointers approach.
For lists I'd create a simple class object that implements metods like __add__() or __len__() or __get__() like in python for example, then when you parse the language you'd substitute list_obj[3] for your_list_obj.method['__get__'] after checking that it exists of course.
What are the advantages of using boost.any library ? Could you please give me some real life examples ? Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
boost::any will happily store ints and floats, types that clearly have no base classes. A real-life example where you can use it is a virtual machine for a high-level interpreted language. Your "function" objects will need an array of arguments. This can easily be implemented with a std::list<boost::any> behind the scenes.
I consider that Boost.Variant should always be preferred as it's non-intrusive and still calls for very structured programming.
But i guess the main idea behind boost.any is to provide the equivalent of java and c# object types. It's a way of saying "yes we can" ! :-)
We've used it in a property map, (std::map<std::string, boost::any>), to store a lot of things dynamically in a simple, flat dataspace.
Mostly we either stored smart-ptr-to-scriptable-objects or strings, but some entries where other types (floats, vec3f, matrices, and other non-standard objects).
It works pretty well for adding more dynamic capabilities to c++, or wherever you want some type-erasure to just add any type of data to an object.
Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
That calls an object hierarchy -- a construct you are injecting in artificially in to the design for solving a peripheral problem. Further, such a construct is easy to get wrong and a wrong implementation can wreak havoc. Boost.Any is a community reviewed safe, well-tested alternative.
Could you please give me some real life examples ?
TinyJSON uses boost.Any.
What are the advantages of using boost.any library ?
I refer the introductory documentation.
We use boost.any as the carrier type for a type-safe tagged variadic container. Here's what that means:
We have a "raft" object, which travels through a set of filters. When a filter wants to add data to the raft, it can do something like this:
raft.addTaggedData<ETag1>(3.0);
raft.addTaggedData<ETag2>("a string")`;
std::string str = raft.getTaggedData<ETag2>();
int a = raft.getTaggedData<ETag1>(); // <-- Compile error
Where ETag1 and ETag2 are members of an enum, and we use a traits template to map tags to types.
The raft class is using a list of pair<ETagType, boost::any> as a backing store. Boost.any saved us the pain of managing raw buffers for various types.