PhoenixGenerator  2.0.0
Set of tools to generate code
wrapper_module_generator.cpp
Go to the documentation of this file.
1 /***************************************
2  Auteur : Pierre Aubert
3  Mail : pierre.aubert@lapp.in2p3.fr
4  Licence : CeCILL-C
5 ****************************************/
6 
7 #include "header_generator.h"
8 #include "saveClassConfig.h"
9 #include "type_utils.h"
10 #include "wrapper_convertType.h"
12 
14 
18  if(type == "int"){return "i";}
19  else if(type == "float"){return "f";}
20  else if(type == "double"){return "d";}
21  else if(type == "char"){return "c";}
22  else if(type == "std::string"){return "s";}
23  else{
24  return "UnknownType";
25  }
26 }
27 
29 
33  if(type == "float" || type == "double"){return "PyFloat_AsDouble";}
34  else if(type == "long" || type == "short" || type == "char"){return "PyLong_AsLong";}
35  else if(type == "int"){return "PyLong_AsInt";}
36  else if(type == "size_t"){return "PyLong_ToSize_t";}
37  else{
38  return "UnknownConvertFunctionToValue";
39  }
40 }
41 
43 
47  if(type == "float" || type == "double"){return "PyFloat_FromDouble";}
48  else if(type == "long" || type == "short" || type == "char" || type == "int"){return "PyLong_FromLong";}
49  else if(type == "unsigned long" || type == "unsigned short" || type == "unsigned char" || type == "unsigned int"){return "PyLong_FromLong";}
50  else if(type == "size_t"){return "PyLong_FromSize_t";}
51  else{
52  return "UnknownConvertFunctionFromValue";
53  }
54 }
55 
57 
61  if(type == "long" || type == "int" || type == "short" || type == "char"){return "int";}
62  else if(type == "float" || type == "double"){return "float";}
63  else if(type == "std::string"){return "std";}
64  else{
65  return "NoPythonTypeYet";
66  }
67 }
68 
70 
73 PString project_wrapper_modulePyTypeReady(const std::vector<PClassConfig> & vecClassConfig){
74  PString body;
75 // bool isPyEnumAvailable(true);
76  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
77  if(it->getIsEnum()){continue;}
78 // if(it->getIsEnum() && isPyEnumAvailable){
79 // body += "\tif(PyType_Ready(&PyEnum_Type) < 0){return NULL;}\n";
80 // isPyEnumAvailable = false;
81 // }
82  body += "\tif(PyType_Ready(&WP"+it->getName()+"Type) < 0){return NULL;}\n";
83  }
84  return body;
85 }
86 
88 
91 PString project_wrapper_modulePyIncref(const std::vector<PClassConfig> & vecClassConfig){
92  PString body;
93 // bool isPyEnumAvailable(true);
94  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
95  if(it->getIsEnum()){
96  body += "\tPyObject* "+it->getName()+"EnumType = WP"+it->getName()+"_newC(NULL, NULL, NULL);\n";
97  body += "\tPy_INCREF("+it->getName()+"EnumType);\n";
98  continue;
99  }
100 // if(it->getIsEnum() && isPyEnumAvailable){
101 // body += "\tPy_INCREF(&PyEnum_Type);\n";
102 // isPyEnumAvailable = false;
103 // }
104  body += "\tPy_INCREF(&WP"+it->getName()+"Type);\n";
105  }
106  return body;
107 }
108 
110 
113 PString project_wrapper_moduleAddObject(const std::vector<PClassConfig> & vecClassConfig){
114  PString body;
115 // bool isPyEnumAvailable(true);
116  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
117  if(it->getIsEnum()){
118  body += "\tPyModule_AddObject(m, \""+it->getName()+"\", "+it->getName()+"EnumType);\n";
119  continue;
120  }
121 // if(it->getIsEnum() && isPyEnumAvailable){
122 // body += "\tPyModule_AddObject(m, \"Enum\", (PyObject *)&PyEnum_Type);\n";
123 // isPyEnumAvailable = false;
124 // }
125  body += "\tPyModule_AddObject(m, \""+it->getName()+"\", (PyObject *)&WP"+it->getName()+"Type);\n";
126  }
127  return body;
128 }
129 
131 
138 bool project_wrapper_moduleGeneratorMain(const PPath & fileName, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
139  PString body, moduleName(projectConfig.name.toLower());
140  body += licenceSaveStr();
141  body += "\n";
142  body += "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\n";
143  body += "#ifndef DISABLE_COOL_ARRAY\n";
144  body += "#\tdefine PY_ARRAY_UNIQUE_SYMBOL "+moduleName+"_ARRAY_API\n";
145  body += "#endif\n";
146  body += "\n";
147  body += "#include <Python.h>\n";
148  body += "#include \"structmember.h\"\n";
149  body += "#include <numpy/arrayobject.h>\n";
150  body += "\n";
151  body += "#include <string>\n";
152 
153  //TODO : put the includes of all class definitions
154  for(PVecPath::const_iterator it(vecInclude.begin()); it != vecInclude.end(); ++it){
155  body += "#include \""+(*it)+"\"\n";
156  }
157  body += "\n";
158  body += "#include \""+ baseImplInclude + "_wrapper.h\"\n\n";
159 
160  body += "static PyMethodDef _"+moduleName+"_methods[] = {\n";
161  body += "\t{NULL, NULL}\n";
162  body += "};\n\n";
163 
164  body += "static PyModuleDef _"+moduleName+"_module = {\n";
165  body += "\tPyModuleDef_HEAD_INIT,\n";
166  body += "\t\"py"+moduleName+"\",\n";
167  body += "\t\"\",\n";
168  body += "\t-1,\n";
169  body += "\t_"+moduleName+"_methods,\n";
170  body += "\tNULL,\n";
171  body += "\tNULL,\n";
172  body += "\tNULL,\n";
173  body += "\tNULL\n";
174  body += "};\n\n";
175 
176  body += "///Create the python module "+moduleName+"\n";
177  body += "/**\t@return python module "+moduleName+"\n";
178  body += "*/\n";
179  body += "PyMODINIT_FUNC PyInit_py"+moduleName+"(void){\n";
180  body += "\tPyObject *m;\n";
181  body += "\timport_array();\n";
182  body += "\n";
183  body += project_wrapper_modulePyTypeReady(vecClassConfig);
184  body += "\t\n";
185  body += "\tm = PyModule_Create(&_"+moduleName+"_module);\n";
186  body += "\tif(m == NULL){\n";
187  body += "\t\treturn NULL;\n";
188  body += "\t}\n";
189  body += "\t\n";
190  body += project_wrapper_modulePyIncref(vecClassConfig);
191  body += "\t\n";
192  body += project_wrapper_moduleAddObject(vecClassConfig);
193  body += "\t\n";
194  body += "\treturn m;\n";
195  body += "}\n\n";
196 
197  return fileName.saveFileContent(body);
198 }
199 
201 
204 PString project_wrapper_moduleGeneratorWrapperHeaderStructPreDef(const std::vector<PClassConfig> & vecClassConfig){
205  PString body;
206  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
207  if(it->getIsEnum()){continue;}
208  body += "struct WP"+it->getName()+";\n";
209  }
210  return body;
211 }
212 
214 
218  PString body;
219  body += "\t" + attr.getDocumentation() + "\n";
220  if(getIsSimpleType(attr.getType())){
221  body += "\t" + attr.getType();
222  }else{
223  body += "\tPyObject *";
224  }
225  body += " "+attr.getName()+";\n";
226  return body;
227 }
228 
230 
235  PString body;
236  //If the type is simple, we do not need getter, setter and other methods
237  if(getIsSimpleType(attr.getType())){return body;}
238  body += "int "+className+"_set"+attr.getName()+"("+className+" * self, PyObject * value, void * closure);\n";
239  body += "PyObject * "+className+"_get"+attr.getName()+"("+className+" * self, void * closure);\n";
240  return body;
241 }
242 
244 
248  PString body, className("WP"+classConfig.getName());
249 // body += classConfig.getClassDocumentation() + "\n";
250 // body += "struct "+className+"{\n";
251 // body += "\tPyObject_HEAD\n";
252 // const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
253 // for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
254 // if(it->getDocumentation() != ""){
255 // body += "\t" + it->getDocumentation() + "\n";
256 // }
257 // body += "\tPyObject * "+it->getName()+";\n";
258 // }
259 // body += "};\n\n";
260 
261 // body += "PyObject * "+className+"_getTypeName(PyObject *self, PyObject *args);\n\n";
262  body += "//Allocation and deallocation\n";
263  body += "PyObject * "+className+"_newC(PyTypeObject * type, PyObject * args, PyObject * kwds);\n";
264 // body += "void "+className+"_dealloc("+className+" * self);\n\n";
265 
266 // body += "//getter and setters\n";
267 // for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
268 // body += project_wrapper_classGetterSetterDef(className, *it);
269 // }
270 // body += "\n";
271 // body += "extern PyGetSetDef "+className+"_getseters[];\n";
272 // body += "extern PyMemberDef "+className+"_members[];\n";
273 // body += "extern PyMethodDef "+className+"_methods[];\n";
274 // body += "extern PyTypeObject "+className+"Type;\n\n";
275  return body;
276 }
277 
279 
283  PString body, className("WP"+classConfig.getName());
284  body += classConfig.getClassDocumentation() + "\n";
285  body += "struct "+className+"{\n";
286  body += "\tPyObject_HEAD\n";
287  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
288  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
289  body += project_wrapper_attributeDef(*it);
290  }
291  body += "};\n\n";
292  body += "//Check function\n";
293  body += "bool "+className+"_check(std::string & error, const "+className+" & obj);\n";
294 
295  body += "//TODO : add new and free for array data\n";
296  body += "//getter and setters\n";
297  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
298  body += project_wrapper_classGetterSetterDef(className, *it);
299  }
300  //Check when we defined std::vector
301  body += "PyObject * "+className+"_getTypeName(PyObject *self, PyObject *args);\n\n";
302  body += "//Allocation and deallocation\n";
303  body += "PyObject * "+className+"_newC(PyTypeObject * type, PyObject * args, PyObject * kwds);\n";
304  body += "void "+className+"_dealloc("+className+" * self);\n\n";
305 
306  body += "//PhoenixDataStream interface\n";
307  body += "PyObject * "+className+"_fromBytes(PyObject *self, PyObject *args);\n";
308  body += "size_t "+className+"_fromMessage("+className+" & obj, DataStreamIter & iter);\n\n";
309 
310  body += "PyObject * "+className+"_toBytes(PyObject *self, PyObject *args);\n";
311  body += "size_t "+className+"_toMessage("+className+" & obj, DataStreamIter & iter);\n\n";
312 
313  body += "PyObject * "+className+"_getSizeInByte(PyObject *self, PyObject *args);\n";
314  body += "size_t "+className+"_getSize("+className+" & obj);\n\n";
315 
316  body += "//PhoenixDataStream interface under the hood for all attributes\n";
317  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
318  body += "//PhoenixDataStream interface under the hood for " + it->getName() + " attribute\n";
319  body += "bool "+className+"_" + it->getName() + "_fromMessage("+className+" & self, DataStreamIter &iter);\n";
320  body += "bool "+className+"_" + it->getName() + "_toMessage("+className+" & self, DataStreamIter &iter);\n";
321  body += "size_t "+className+"_" + it->getName() + "_getSize("+className+" & self);\n\n";
322  }
323 
324  body += "extern PyGetSetDef "+className+"_getseters[];\n";
325  body += "extern PyMemberDef "+className+"_members[];\n";
326  body += "extern PyMethodDef "+className+"_methods[];\n";
327  body += "extern PyTypeObject "+className+"Type;\n\n";
328  return body;
329 }
330 
332 
335 PString project_wrapper_moduleGeneratorWrapperHeaderAllStructDef(const std::vector<PClassConfig> & vecClassConfig){
336  PString body;
337  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
338  if(it->getIsEnum()){
340  }else{
342  }
343 
344  }
345  return body;
346 }
347 
349 
356 bool project_wrapper_moduleGeneratorWrapperHeader(const PPath & wrapperHeader, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
357  PString body;
358  body += licenceSaveStr();
359  body += "\n";
360  PString includeMacro("__" + baseImplInclude.toUpper() + "_WRAPPER_H__");
361  body += "#ifndef "+includeMacro+"\n";
362  body += "#define "+includeMacro+"\n\n";
363 
364  body += "#include <Python.h>\n";
365  body += "#include <structmember.h>\n";
366  body += "#include <iostream>\n\n";
367  body += "#include \"phoenix_data_stream.h\"\n\n";
369  body += "\n";
371 
372  body += "#endif\n\n";
373  return wrapperHeader.saveFileContent(body);
374 }
375 
377 
382 PString project_wrapper_classImplPythonType(const PClassConfig & classConfig, const PString & moduleName, const PString & fromOtherType){
383  PString body, className("WP"+classConfig.getName());
384 
385  body += "///Define the type of the "+className+"\n";
386  body += "PyTypeObject "+className+"Type = {\n";
387  body += "\tPyVarObject_HEAD_INIT("+fromOtherType+", 0)\n";
388  body += "\t\""+moduleName+"."+classConfig.getName()+"\", /* tp_name */\n";
389  body += "\tsizeof("+className+"), /* tp_basicsize */\n";
390  body += "\t0, /* tp_itemsize */\n";
391  body += "\t(destructor)"+className+"_dealloc, /* tp_dealloc */\n";
392  body += "\t0, /* tp_print */\n";
393  body += "\t0, /* tp_getattr */\n";
394  body += "\t0, /* tp_setattr */\n";
395  body += "\t0, /* tp_reserved */\n";
396  body += "\t0, /* tp_repr */\n";
397  body += "\t0, /* tp_as_number */\n";
398  body += "\t0, /* tp_as_sequence */\n";
399  body += "\t0, /* tp_as_mapping */\n";
400  body += "\t0, /* tp_hash */\n";
401  body += "\t0, /* tp_call */\n";
402  body += "\t0, /* tp_str */\n";
403  body += "\t0, /* tp_getattro */\n";
404  body += "\t0, /* tp_setattro */\n";
405  body += "\t0, /* tp_as_buffer */\n";
406  body += "\tPy_TPFLAGS_DEFAULT |\n";
407  body += "\tPy_TPFLAGS_BASETYPE, /* tp_flags */\n";
408  body += "\t\""+className+" doc : "+classConfig.getClassDocumentation().replace("///", "")+"\", /* tp_doc */\n";
409  body += "\t0, /* tp_traverse */\n";
410  body += "\t0, /* tp_clear */\n";
411  body += "\t0, /* tp_richcompare */\n";
412  body += "\t0, /* tp_weaklistoffset */\n";
413  body += "\t0, /* tp_iter */\n";
414  body += "\t0, /* tp_iternext */\n";
415  body += "\t"+className+"_methods, /* tp_methods */\n";
416  body += "\t"+className+"_members, /* tp_members */\n";
417  body += "\t"+className+"_getseters,/* tp_getset */\n";
418  body += "\t0, /* tp_base */\n";
419  body += "\t0, /* tp_dict */\n";
420  body += "\t0, /* tp_descr_get */\n";
421  body += "\t0, /* tp_descr_set */\n";
422  body += "\t0, /* tp_dictoffset */\n";
423  body += "\t0, /* tp_init */\n";
424  body += "\t0, /* tp_alloc */\n";
425  body += "\t"+className+"_newC, /* tp_new */\n";
426  body += "};\n\n";
427  return body;
428 }
429 
431 
436  PString body, className("WP"+classConfig.getName());
437 
438  body += "///Allocate the "+className+"\n";
439  body += "/**\t@param type : type variable\n";
440  body += " * \t@param args : args variable\n";
441  body += " * \t@param kwds : kwds variable\n";
442  body += " * \t@return object to be allocated\n";
443  body += "*/\n";
444  body += "PyObject * "+className+"_newC(PyTypeObject * type, PyObject * args, PyObject * kwds){\n";
445  body += "\t"+className+" *self;\n";
446  body += "\tself = ("+className+" *)type->tp_alloc(type, 0);\n";
447  body += "\tif(self != NULL){\n";
448  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
449  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
450  PString attrType(it->getType());
451  if(getIsSimpleType(attrType)){
452  body += "\t\tself->"+it->getName()+" = 0;\n";
453  }else if(attrType == "std::string"){
454  body += "\t\tself->"+it->getName()+" = Py_BuildValue(\"s\", \"\");\n";
455  }else if(attrType == "DataStreamMsg"){
456  body += "\t\tself->"+it->getName()+" = PyByteArray_FromStringAndSize(\"\", 0lu);\n";
457  }else if(generator_typeIsList(attrType)){
458  body += "\t\tself->"+it->getName()+" = PyList_New(0);\n";
459  }else{
460  //TODO : check for complex types, vector, map, and nested types
461  if(it->getIsEnum()){
462  body += "\t\t//There is not type for enum because of the very ugly trick of Python\n";
463  body += "\t\tself->"+it->getName()+" = WP"+attrType+"_newAttributeC();\n";
464  }else{
465  body += "\t\tself->"+it->getName()+" = WP"+attrType+"_newC(&WP"+attrType+"Type, NULL, NULL);\n";
466  }
467  }
468  }
469  body += "\t}\n";
470  body += "\treturn (PyObject *)self;\n";
471  body += "}\n\n";
472  return body;
473 }
474 
476 
481  PString body, className("WP"+classConfig.getName());
482 
483  body += "///Deallocate the structure "+className+"\n";
484  body += "/**\t@param self : object to be deallocated\n";
485  body += "*/\n";
486  body += "void "+className+"_dealloc("+className+" * self){\n";
487  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
488  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
489  if(!getIsSimpleType(it->getType())){
490  PString attrName = it->getName();
491  body += "\t//Free the "+attrName+" attribute\n";
492  body += "\tPyObject* "+attrName+"_tmp = self->"+attrName+";\n";
493  body += "\tself->"+attrName+" = NULL;\n";
494  body += "\tPy_XDECREF("+attrName+"_tmp);\n";
495  }
496  }
497  body += "}\n\n";
498  return body;
499 }
500 
502 
506  PString body, className("WP"+classConfig.getName());
507  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
508  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
509  if(!getIsSimpleType(it->getType())){
510  PString attrName(it->getName()), attrDoc(it->getDocumentation());
511  body += "///Setter of the "+attrName+"\n";
512  body += "/**\t@param self : object "+className+"\n";
513  body += " * \t@param value : "+attrDoc+"\n";
514  body += " * \t@param closure : object closure for python API (it is a wrapper python grosse bidouille)\n";
515  body += " * \t@return 0 on success, -1 otherwise\n";
516  body += "*/\n";
517  body += "int "+className+"_set"+attrName+"("+className+" * self, PyObject * value, void * closure){\n";
518  body += "\tif(value == NULL){\n";
519  body += "\t\tPyErr_SetString(PyExc_TypeError, \"Cannot delete the "+className+"."+attrName+" attribute\");\n";
520  body += "\t\treturn -1;\n";
521  body += "\t}\n";
522  body += "\tPy_DECREF(self->"+attrName+");\n";
523  body += "\tPy_INCREF(value);\n";
524  body += "\tself->"+attrName+" = value;\n";
525  body += "\treturn 0;\n";
526  body += "}\n\n";
527 
528  body += "///Setter of the "+attrName+"\n";
529  body += "/**\t@param self : object "+className+"\n";
530  body += " * \t@param closure : object closure for python API (it is a wrapper python grosse bidouille)\n";
531  body += " * \t@return "+attrDoc+"\n";
532  body += "*/\n";
533  body += "PyObject * "+className+"_get"+attrName+"("+className+" * self, void * closure){\n";
534  body += "\tPy_INCREF(self->"+attrName+");\n";
535  body += "\treturn self->"+attrName+";\n";
536  body += "}\n\n";
537  }
538  }
539  return body;
540 }
541 
543 
547  PString body;
548  body += "\tif(!PyArg_ParseTuple(args, \"O\", &"+varName+")){\n";
549  body += "\t\tPyErr_SetString(PyExc_RuntimeError, \"missing filename or keyword not supported\\n\");\n";
550  body += "\t\treturn NULL;\n";
551  body += "\t}\n";
552  return body;
553 }
554 
556 
560 PString project_wrapper_classPythonFromBytes(const PClassConfig & classConfig, const PString & className){
561  PString body;
562  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
563  body += "///Initialise a "+className+" with a ByteArray\n";
564  body += "/**\t@param self : pointer to the "+className+"\n";
565  body += " * \t@param args : PyByteArray to initialise the "+className+"\n";
566  body += " * \t@return Py_RETURN_NONE\n";
567  body += "*/\n";
568  body += "PyObject * "+className+"_fromBytes(PyObject *self, PyObject *args){\n";
569  body += "\t"+className+"* obj = ("+className+"*)self;\n";
570  body += "\tPyObject * byteArray = NULL;\n";
571  body += getObjectParseTuple("byteArray");
572  body += "\t//We hvae to check if byteArray is a 'bytearray'\n";
573  body += "\tstd::string inputTypeName(PyUnicode_AsUTF8(PyType_GetName(Py_TYPE(byteArray))));\n";
574  body += "\tif(inputTypeName != \"bytearray\"){\n";
575  body += "\t\tstd::string error(\""+className+"_fromBytes : cannot load "+className+" with given '\"+inputTypeName+\"', expecting 'bytearray'\\n\");\n";
576  body += "\t\tPyErr_SetString(PyExc_RuntimeError, error.c_str());\n";
577  body += "\t\treturn NULL;\n";
578  body += "\t}\n";
579  body += "\tsize_t nbByte = PyByteArray_Size(byteArray);\n";
580  body += "\tif(nbByte == 0lu){\n";
581  body += "\t\tPy_RETURN_NONE;\n";
582  body += "\t}\n";
583  body += "\tDataStreamIter iter = (DataStreamIter)PyByteArray_AsString(byteArray);\n";
584  body += "\tif(!"+className+"_fromMessage(*obj, iter)){\n";
585  body += "\t\tPyErr_SetString(PyExc_RuntimeError, \""+className+"_fromBytes : cannot load "+className+" with given PyByteArray\\n\");\n";
586  body += "\t\treturn NULL;\n";
587  body += "\t}\n";
588  body += "\tPy_RETURN_NONE;\n";
589  body += "}\n\n";
590 
591  body += "///Load a "+className+" from a DataStreamIter\n";
592  body += "/**\t@param obj : reference to the "+className+"\n";
593  body += " * \t@param iter : DataStreamIter to be used\n";
594  body += " * \t@return true on success, false otherwise\n";
595  body += "*/\n";
596  body += "size_t "+className+"_fromMessage("+className+" & obj, DataStreamIter & iter){\n";
597  body += "\tbool b(true);\n";
598  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
599  const PString & attrName = it->getName();
600  body += "\tb &= "+className+"_"+attrName+"_fromMessage(obj, iter);\n";
601  }
602  body += "\treturn b;\n";
603  body += "}\n\n";
604  return body;
605 }
606 
608 
612 PString projecy_wrapper_classCheckCall(const PString & className, const PString & functionName){
613  PString body;
614  body += "\t//In case of emergency : check the integrity of the types before getting the size of to ensure all attributes have to good type\n";
615  body += "\tstd::stringstream error(\"\");\n";
616  body += "\tif(!"+className+"_check(error, *obj)){\n";
617  body += "\t\tstd::string errorText(\""+functionName+" : check of class "+className+" failled\\n\" + error.str());\n";
618  body += "\t\tPyErr_SetString(PyExc_RuntimeError, errorText.c_str());\n";
619  body += "\t\treturn NULL;\n";
620  body += "\t}\n";
621  return body;
622 }
623 
625 
629 PString project_wrapper_classPythonToBytes(const PClassConfig & classConfig, const PString & className){
630  PString body;
631  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
632  body += "///Convert a "+className+" to a ByteArray\n";
633  body += "/**\t@param self : pointer to the "+className+"\n";
634  body += " * \t@param args : not used\n";
635  body += " * \t@return PyByteArray which contains data of the "+className+"\n";
636  body += "*/\n";
637  body += "PyObject * "+className+"_toBytes(PyObject *self, PyObject *args){\n";
638  body += "\t"+className+"* obj = ("+className+"*)self;\n";
639  body += projecy_wrapper_classCheckCall(className, className+"_toBytes");
640  body += "\tsize_t nbByte = "+className+"_getSize(*obj);\n";
641  body += "\tif(nbByte == 0lu){\n";
642  body += "\t\tPyErr_SetString(PyExc_RuntimeError, \"project_wrapper_classPythonToBytes : cannot serialise "+className+" of size 0 into a PyByteArray\\n\");\n";
643  body += "\t\treturn NULL;\n";
644  body += "\t}\n";
645  body += "\tDataStreamMsg msg(nbByte);\n";
646  body += "\tDataStreamIter iter = msg.data();\n";
647  body += "\t\n";
648  body += "\tif(!"+className+"_toMessage(*obj, iter)){\n";
649  body += "\t\tPyErr_SetString(PyExc_RuntimeError, \"project_wrapper_dataStreamMethod : cannot save "+className+" into a PyByteArray\\n\");\n";
650  body += "\t\treturn NULL;\n";
651  body += "\t}\n";
652  body += "\treturn PyByteArray_FromStringAndSize((const char*)msg.data(), nbByte);\n";
653  body += "}\n\n";
654 
655  body += "///Write a "+className+" in a DataStreamIter\n";
656  body += "/**\t@param obj : reference to the "+className+"\n";
657  body += " * \t@param iter : DataStreamIter to be used\n";
658  body += " * \t@return true on success, false otherwise\n";
659  body += "*/\n";
660  body += "size_t "+className+"_toMessage("+className+" & obj, DataStreamIter & iter){\n";
661  body += "\tbool b(true);\n";
662  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
663  const PString & attrName = it->getName();
664  body += "\tb &= "+className+"_"+attrName+"_toMessage(obj, iter);\n";
665  }
666  body += "\treturn b;\n";
667  body += "}\n\n";
668  return body;
669 }
670 
672 
677  PString body;
678  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
679  body += "///Get the size in bytes of "+className+" for Python API\n";
680  body += "/**\t@param self : pointer to the "+className+"\n";
681  body += " * \t@param args : not used\n";
682  body += " * \t@return size of the "+className+" in bytes\n";
683  body += "*/\n";
684  body += "PyObject * "+className+"_getSizeInByte(PyObject *self, PyObject *args){\n";
685  body += "\t"+className+"* obj = ("+className+"*)self;\n";
686  body += projecy_wrapper_classCheckCall(className, className+"_getSizeInByte");
687  body += "\tsize_t nbByte = "+className+"_getSize(*obj);\n";
688  body += "\treturn Py_BuildValue(\"k\", nbByte);\n";
689  body += "}\n\n";
690 
691  body += "///Get the size of a "+className+"\n";
692  body += "/**\t@param obj : reference to the "+className+" to be used\n";
693  body += " * \t@return size of the "+className+" in bytes\n";
694  body += "*/\n";
695  body += "size_t "+className+"_getSize("+className+" & obj){\n";
696  body += "\tsize_t nbByte(0lu);\n";
697  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
698  const PString & attrName = it->getName();
699  body += "\tnbByte += "+className+"_"+attrName+"_getSize(obj);\n";
700  }
701  body += "\treturn nbByte;\n";
702  body += "}\n\n";
703  return body;
704 }
705 
707 
712  PString body;
713  const PString & attrName = attr.getName(), & type(attr.getType());
714  bool isSimpleType(getIsSimpleType(type));
715  PString callAttr("self."+attrName);
716  body += "///Load a "+className+"."+attrName+" from a DataStreamMsg\n";
717  body += "/**\t@param self : reference to the "+className+"\n";
718  body += " * \t@param iter : DataStreamIter to be used\n";
719  body += " * \t@return true on success, false otherwise\n";
720  body += "*/\n";
721  PString functionName(className+"_" + attrName + "_fromMessage");
722  body += "bool "+functionName + "("+className+" & self, DataStreamIter & iter){\n";
723  if(isSimpleType){
724  body += "\treturn DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, "+callAttr+");\n";
725  }else if(type == "std::string"){
726  body += "\tstd::string tmpStr(\"\");\n";
727  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, tmpStr)){return false;};\n";
728 // body += "\tself."+attrName+" = PyBytes_FromStringAndSize(tmpStr.c_str(), tmpStr.size());\n";
729 // body += "\tself."+attrName+" = PyUnicode_FromStringAndSize(tmpStr.c_str(), tmpStr.size());\n";
730  body += "\tself."+attrName+" = PyUnicode_DecodeFSDefaultAndSize(tmpStr.c_str(), tmpStr.size());\n";
731  body += "\treturn true;\n";
732  }else if(type == "DataStreamMsg"){
733  body += "\tDataStreamMsg message;\n";
734  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+type+">::data_stream(iter, message)){return false;};\n";
735  body += "\tself."+attrName+" = PyByteArray_FromStringAndSize((const char*)message.data(), message.size());\n";
736  body += "\treturn true;\n";
737  }else if(generator_typeIsList(type)){
738  body += "\tsize_t nbElement(0lu);\n";
739  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, size_t>::data_stream(iter, nbElement)){return false;};\n";
740  body += "\tif(nbElement == 0lu){return true;}\t//The list can be empty\n";
741  body += "\t"+callAttr+" = PyList_New(nbElement);\n";
742  body += "\tfor(size_t i(0lu); i < nbElement; ++i){\t//Then we load the content of the list\n";
743  PString nestedType(generator_getListNestedType(type));
744  if(getIsSimpleType(nestedType)){
745  body += "\t\t"+nestedType+" value = 0;\n";
746  body += "\t\tif(!DataStream<DataStreamIter, DataStreamMode::READ, "+nestedType+">::data_stream(iter, value)){return false;};\n";
747  body += "\t\tPyObject * el = "+wrapper_getValueToObject(nestedType)+"(value);\n";
748 // body += "\t\tPyObject * el = Py_BuildValue(\""+wrapper_getBuildValueStr(nestedType)+"\", value);\n";
749  body += "\t\tPyList_SET_ITEM("+callAttr+", i, el);\n";
750  }else{
751  body += "\t\t//If it is not a predefined type, we cannot deal with it\n";
752  body += "\t\tWP"+nestedType+" * el = (WP"+nestedType+"*)WP"+nestedType+"_newC(&WP"+nestedType+"Type, NULL, NULL);\n";
753  body += "\t\tif(!WP"+nestedType+"_fromMessage(*el, iter)){return false;}\n";
754  body += "\t\tPyList_SET_ITEM("+callAttr+", i, el);\n";
755  }
756  body += "\t}\n";
757  body += "\treturn true;\n";
758  }else if(attr.getIsEnum()){
759  body += "\t//TODO : implement the load from a message of type "+type+"\n";
760  body += "\t//We know, for sure it is an Enum but we have to figure out how we are supposed to deal with it inside the wrapper\n";
761  body += "\t//And I really wanted to avoid to call the interpreter once more each time we want to deserialise an Enum\n";
762  body += "\tint enumValue = 0;\n";
763  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::READ, int>::data_stream(iter, enumValue)){\n";
764  body += "\t\tstd::cerr << \""+functionName+" : cannot read enum value\" << std::endl;\n";
765  body += "\t\treturn false;\n";
766  body += "\t}\n";
767 // body += "\tif(PyObject_SetAttrString("+callAttr+", \"value\", PyLong_FromLong(enumValue)) != 0){\n";
768 // body += "\t\tstd::cerr << \""+functionName+" : cannot set enum value(\"<<enumValue<<\") in PyObject\" << std::endl;\n";
769 // body += "\t\treturn false;\n";
770 // body += "\t}\n";
771  body += "\tstd::map<int, std::string>::const_iterator it = WP"+type+"EnumValue.find(enumValue);\n";
772  body += "\tif(it == WP"+type+"EnumValue.end()){\n";
773  body += "\t\tstd::cerr << \""+functionName+" : cannot find enum value \" << enumValue << \" in map WP"+type+"EnumValue\" << std::endl;\n";
774  body += "\t\treturn false;\n";
775  body += "\t}\n";
776 
777  body += "\tPy_DECREF("+callAttr+");\n";
778  body += "\t"+callAttr+" = WP"+type+"_newGeneric(\"_var_______ = "+type+".\" + it->second, \"_var_______\");\n";
779  body += "\treturn true;\n";
780 
781 // body += "\treturn PyObject_SetAttrString("+callAttr+", \"name\", PyUnicode_FromStringAndSize(it->second.c_str(), it->second.size())) == 0;\n";
782  }else{
783  body += "\t//TODO : implement the load from a message of type "+type+"\n";
784  body += "\treturn true;\n";
785  }
786  body += "}\n\n";
787 
788  return body;
789 }
790 
792 
797  PString body;
798  const PString & attrName = attr.getName(), & type(attr.getType());
799  bool isSimpleType(getIsSimpleType(type));
800  PString callAttr("self."+attrName);
801  body += "///Convert a "+className+"."+attrName+" to a DataStreamMsg\n";
802  body += "/**\t@param self : reference to the "+className+"\n";
803  body += " * \t@param iter : DataStreamIter to be used\n";
804  body += " * \t@return true on success, false otherwise\n";
805  body += "*/\n";
806  body += "bool "+className+"_" + attrName + "_toMessage("+className+" & self, DataStreamIter & iter){\n";
807  if(isSimpleType){
808  body += "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, "+type+">::data_stream(iter, "+callAttr+");\n";
809  }else if(type == "std::string"){
810 // body += "\tsize_t nbChar(PyUnicode_GetLength("+callAttr+"));\n"; //PyUnicode_GET_LENGTH
811  body += "\tlong nbChar(0lu);\n";
812  body += "\tconst char * ptr = PyUnicode_AsUTF8AndSize("+callAttr+", &nbChar);\n";
813 
814  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, long>::data_stream(iter, nbChar)){return false;}\n";
815 // body += "\tconst char * ptr = PyBytes_AsString("+callAttr+");\n"; //PyBytes_AsString
816  body += "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, char>::data_stream(iter, (char*)ptr, nbChar);\n";
817  }else if(type == "DataStreamMsg"){
818  body += "\tsize_t nbByte(PyByteArray_Size("+callAttr+"));\n";
819  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, size_t>::data_stream(iter, nbByte)){return false;}\n";
820  body += "\tif(nbByte == 0lu){return true;}\t//The bytearray can be empty\n";
821  body += "\tDataStreamIter dataPtr = (DataStreamIter)PyByteArray_AsString("+callAttr+");\n";
822  body += "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, DataStreamType>::data_stream(iter, dataPtr, nbByte);\n";
823  }else if(generator_typeIsList(type)){
824  body += "\tsize_t nbElement(PyByteArray_Size("+callAttr+"));\n";
825  body += "\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, size_t>::data_stream(iter, nbElement)){return false;}\n";
826  body += "\tif(nbElement == 0lu){return true;}\t//The list can be empty\n";
827  body += "\tfor(size_t i(0lu); i < nbElement; ++i){\t//Then the content of the list\n";
828  PString nestedType(generator_getListNestedType(type));
829  if(getIsSimpleType(nestedType)){
830  body += "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
831  body += "\t\t"+nestedType+" value = "+wrapper_getObjectToValue(nestedType)+"(el);\n";
832  body += "\t\tif(!DataStream<DataStreamIter, DataStreamMode::WRITE, "+nestedType+">::data_stream(iter, value)){return false;}\n";
833  }else{
834  body += "\t\t//If it is not a predefined type, we cannot deal with it\n";
835  body += "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
836  body += "\t\tif(!WP"+nestedType+"_toMessage((WP"+nestedType+"&)*el, iter)){return false;}\n";
837  }
838  body += "\t}\n";
839  body += "\treturn true;\n";
840  }else if(attr.getIsEnum()){
841  body += "\t//TODO : implement the save to a message of type "+type+"\n";
842  body += "\t//We know, for sure it is an Enum but we have to figure out how we are supposed to deal with it inside the wrapper\n";
843  body += "\t//And I really wanted to avoid to call the interpreter once more each time we want to serialise an Enum\n";
844  body += "\tPyObject * attrValue = PyObject_GetAttrString("+callAttr+", \"value\");\n";
845  body += "\tif(attrValue == NULL){return false;}\n";
846  body += "\t//Now we have to get the integer inside the attribute\n";
847  body += "\tint enumValue = PyLong_AsInt(attrValue);\n";
848  body += "\treturn DataStream<DataStreamIter, DataStreamMode::WRITE, int>::data_stream(iter, enumValue);\n";
849  }else{
850  body += "\t//TODO : implement the save to a message of type "+type+"\n";
851  body += "\treturn true;\n";
852  }
853  body += "}\n\n";
854  return body;
855 }
856 
858 
863  PString body;
864  const PString & attrName = attr.getName(), & type(attr.getType());
865  bool isSimpleType(getIsSimpleType(type));
866  PString callAttr("self."+attrName);
867  body += "///Get the size of "+className+"."+attrName+" in bytes\n";
868  body += "/**\t@param self : reference to the "+className+"\n";
869  body += " * \t@return size of "+className+"."+attrName+" in bytes\n";
870  body += "*/\n";
871  body += "size_t "+className+"_" + attrName + "_getSize("+className+" & self){\n";
872  body += "\tsize_t nbByte(0lu);\n";
873  if(isSimpleType){
874  body += "\tDataStream<size_t, DataStreamMode::WRITE, "+type+">::data_stream(nbByte, "+callAttr+");\n";
875  }else if(type == "std::string"){
876  body += "\tnbByte += sizeof(size_t) + PyUnicode_GetLength("+callAttr+");\n"; //PyBytes_Size
877  }else if(type == "DataStreamMsg"){
878  body += "\tnbByte += sizeof(size_t) + PyByteArray_Size("+callAttr+");\n"; //PyBytes_Size
879  }else if(generator_typeIsList(type)){
880  body += "\tnbByte += sizeof(size_t);\t//First the size of the number of elements in the list\n";
881  PString nestedType(generator_getListNestedType(type));
882  if(getIsSimpleType(nestedType)){
883  body += "\tnbByte += sizeof("+nestedType+")*PyList_Size("+callAttr+");\t//Then the content of the list\n";
884  }else{
885  body += "\t//If it is not a predefined type, we cannot deal with it\n";
886  body += "\tfor(long i(0l); i < PyList_Size("+callAttr+"); ++i){\t//Then the content of the list\n";
887  body += "\t\tPyObject * el = PyList_GET_ITEM("+callAttr+", i);\n";
888  body += "\t\tnbByte += WP"+nestedType+"_getSize((WP"+nestedType+"&)*el);\n";
889  body += "\t}\n";
890  }
891  }else if(attr.getIsEnum()){
892  body += "\t//The size of an Enum is the size of an integer\n";
893  body += "\tnbByte += sizeof(int);\n";
894  }else{
895  body += "\t//TODO : implement the get size of type "+type+"\n";
896  }
897  body += "\treturn nbByte;\n";
898  body += "}\n\n";
899  return body;
900 }
901 
903 
907 PString project_wrapper_dataStreamMethod(const PClassConfig & classConfig, const PString & className){
908  PString body;
909  body += project_wrapper_classPythonFromBytes(classConfig, className);
910  body += project_wrapper_classPythonToBytes(classConfig, className);
911  body += project_wrapper_classPythonGetSizeInBytes(classConfig, className);
912  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
913  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
914  body += project_wrapper_classAttributeFromMessage(className, *it);
915  body += project_wrapper_classAttributeToMessage(className, *it);
916  body += project_wrapper_classAttributeGetSize(className, *it);
917  }
918  return body;
919 }
920 
922 
928 PString project_wrapper_callAttributeCheck(const PString & className, const PClassAttribute & attr, const PString & moduleName, const PString & expectedType){
929  PString body, attrType(attr.getType()), attrName(attr.getName());
930  PString typeNameVar(attrName+"Name");
931  body += "\tstd::string "+typeNameVar+"(PyUnicode_AsUTF8(PyType_GetName(Py_TYPE(obj."+attrName+"))));\n";
932  body += "\tif("+typeNameVar+" != \""+expectedType+"\"){\n";
933  body += "\t\terror << \"- Type of attribute "+className+"::"+attrName+" is '\"<<"+typeNameVar+"<<\"' and not expected '"+expectedType+"'\\n\";\n";
934  body += "\t\tb = false;\n";
935  body += "\t}\n";
936  return body;
937 }
938 
940 
944 PString project_wrapper_classImplCheck(const PClassConfig & classConfig, const PString & moduleName){
945  PString body, className("WP"+classConfig.getName());
946  body += "///Check if the "+className+" contains all the expected types\n";
947  body += "/**\t@param[out] error : error to be set if there is one\n";
948  body += " * \t@param obj : reference to the "+className+"\n";
949  body += " * \t@return true if the class "+className+" contains expected types, false otherwise\n";
950  body += "*/\n";
951  body += "bool "+className+"_check(std::stringstream & error, const "+className+" & obj){\n";
952  body += "\tbool b(true);\n";
953  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
954  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
955  PString attrType(it->getType());
956  if(getIsSimpleType(attrType)){
957  continue;
958  }
959  PString attrName(it->getName());
960  body += "\t//Check of the attribute "+attrName+" of type "+attrType+"\n";
961  if(attrType == "std::string"){
962  body += project_wrapper_callAttributeCheck(className, *it, moduleName, "str");
963  }else if(attrType == "DataStreamMsg"){
964  body += project_wrapper_callAttributeCheck(className, *it, moduleName, "bytearray");
965  }else if(generator_typeIsList(attrType)){
966  PString nestedType(generator_getListNestedType(attrType));
967  body += project_wrapper_callAttributeCheck(className, *it, moduleName, "list");
968  body += "\t//Now we have to check all elements of "+attrName+"\n";
969  body += "\tif(b){\t//If obj."+attrName+" is not a list we will have a problem\n";
970  body += "\t\tfor(long i(0l); i < PyList_Size(obj."+attrName+"); ++i){\n";
971  body += "\t\t\tPyObject * el = PyList_GET_ITEM(obj."+attrName+", i);\n";
972  body += "\t\t\tstd::string elType(PyUnicode_AsUTF8(PyType_GetName(Py_TYPE(el))));\n";
973  PString expectedType(moduleName + "." + nestedType);
974  if(getIsSimpleType(nestedType)){
975  expectedType = wrapper_getExpectedType(nestedType);
976  }else{
977  body += "\t\t\t//TODO : For some reason python and ipython agree to tell type("+nestedType+") is "+expectedType+" but during my test I get "+nestedType+" so I add it but I don't know why\n";
978  }
979  body += "\t\t\tif(elType != \""+expectedType+"\" && elType != \""+nestedType+"\"){\n";
980  body += "\t\t\t\terror << \"- Type of element "+className+"::"+attrName+"[\"<<i<<\"] is '\"+elType+\"' and not expected '"+expectedType+"'\\n\";\n";
981  body += "\t\t\t\tb = false;\n";
982  body += "\t\t\t}\n";
983  body += "\t\t}\n";
984  body += "\t}\n";
985  }else if(it->getIsEnum()){
986  body += "\t//Let's check the enum\n";
987  body += project_wrapper_callAttributeCheck(className, *it, moduleName, it->getType());
988  }
989  }
990  body += "\treturn b;\n";
991  body += "}\n\n";
992  return body;
993 }
994 
996 
1001 PString project_wrapper_enumImplPythonType(const PClassConfig & classConfig, const PString & moduleName, const PString & fromOtherType){
1002  PString body, className("WP"+classConfig.getName());
1003  //TODO : remove this function
1004  body += "///Define the type of the "+className+"\n";
1005  body += "PyTypeObject "+className+"Type = {\n";
1006  body += "\tPyVarObject_HEAD_INIT("+fromOtherType+", 0)\n";
1007  body += "\t\""+moduleName+"."+classConfig.getName()+"\", /* tp_name */\n";
1008  body += "\tsizeof("+className+"), /* tp_basicsize */\n";
1009  body += "\t0, /* tp_itemsize */\n";
1010  body += "\t(destructor)"+className+"_dealloc, /* tp_dealloc */\n";
1011  body += "\t0, /* tp_print */\n";
1012  body += "\t0, /* tp_getattr */\n";
1013  body += "\t0, /* tp_setattr */\n";
1014  body += "\t0, /* tp_reserved */\n";
1015  body += "\t0, /* tp_repr */\n";
1016  body += "\t0, /* tp_as_number */\n";
1017  body += "\t0, /* tp_as_sequence */\n";
1018  body += "\t0, /* tp_as_mapping */\n";
1019  body += "\t0, /* tp_hash */\n";
1020  body += "\t0, /* tp_call */\n";
1021  body += "\t0, /* tp_str */\n";
1022  body += "\tPyObject_GenericGetAttr, /* tp_getattro */\n";
1023  body += "\t0, /* tp_setattro */\n";
1024  body += "\t0, /* tp_as_buffer */\n";
1025  body += "\tPy_TPFLAGS_DEFAULT |\n";
1026  body += "\tPy_TPFLAGS_BASETYPE, /* tp_flags */\n";
1027  body += "\t\""+className+" doc : "+classConfig.getClassDocumentation().replace("///", "")+"\", /* tp_doc */\n";
1028  body += "\t0, /* tp_traverse */\n";
1029  body += "\t0, /* tp_clear */\n";
1030  body += "\t0, /* tp_richcompare */\n";
1031  body += "\t0, /* tp_weaklistoffset */\n";
1032  body += "\t0, /* tp_iter */\n";
1033  body += "\t0, /* tp_iternext */\n";
1034  body += "\t"+className+"_methods, /* tp_methods */\n";
1035  body += "\t"+className+"_members, /* tp_members */\n";
1036  body += "\t"+className+"_getseters,/* tp_getset */\n";
1037  body += "\t0, /* tp_base */\n";
1038  body += "\t0, /* tp_dict */\n";
1039  body += "\t0, /* tp_descr_get */\n";
1040  body += "\t0, /* tp_descr_set */\n";
1041  body += "\t0, /* tp_dictoffset */\n";
1042  body += "\t0, /* tp_init */\n";
1043  body += "\tPyType_GenericAlloc, /* tp_alloc */\n";
1044  body += "\t"+className+"_newC, /* tp_new */\n";
1045  body += "};\n\n";
1046  return body;
1047 }
1048 
1050 
1055  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
1056  PString body, pythonClassName(classConfig.getName());
1057  PString className("WP"+pythonClassName);
1058  if(vecAttr.size() == 0lu){return "#error \""+className+" error : Missing enum values as attribute !\"";}
1059  body += "///Generic function to create a "+className+" or a variable\n";
1060  body += "/**\t@param extraPythonCode : extra python code to be added to the existing one\n";
1061  body += " * \t@param objectName : name of the object to get\n";
1062  body += " * \t@return pointer to the asked object name or NULL if the object was not found\n";
1063  body += "*/\n";
1064  body += "PyObject* "+className+"_newGeneric(const std::string & extraPythonCode, const std::string & objectName){\n";
1065  body += "\t//First let's write the python code in a string\n";
1066  body += "\t//Important note : it there is no default value of the enumerate values, we get a nice segmentation fault because why not\n";
1067  body += "\tstd::string pythonStr(\"from enum import Enum\\n\"\n";
1068  body += "\t\t\"class "+pythonClassName+"(Enum):\\n\"\n";
1069  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
1070  body += "\t\t\"\t"+it->getName();
1071  body += " = " + it->getDefaultValue();
1072  body += "\\n\"\n";
1073  }
1074  body += "\t\t\"\tdef getTypeName():\\n\"\n";
1075  body += "\t\t\"\t\treturn \\\""+pythonClassName+"\\\"\\n\"\n";
1076  body += "\t\t\"\");\n";
1077  body += "\tpythonStr += extraPythonCode;\n";
1078  body += "\t//Now, we create the global dictionnary of python\n";
1079  body += "\tPyObject *global_dict = PyDict_New(), *outputEnum = NULL;\n";
1080  body += "\tif(global_dict){\t//If we can create the global_dict\n";
1081  body += "\t\tif(PyRun_String(pythonStr.c_str(), Py_file_input, global_dict, global_dict)){\t//If Python is happy\n";
1082  body += "\t\t\t//We try to get our enum back from the interpretor\n";
1083  body += "\t\t\toutputEnum = PyDict_GetItemString(global_dict, objectName.c_str());\n";
1084  body += "\t\t}\n";
1085  body += "\t}\n";
1086  body += "\tif(!outputEnum){\n";
1087  body += "\t\tPyErr_SetString(PyExc_KeyError, \""+className+"_newGeneric : could not get 'objectName' with the ugly trick due to the fact that using an enum in a wrapper is even worst than using numpy\");\n";
1088  body += "\t}else{\n";
1089  body += "\t\tPy_INCREF(outputEnum);\n";
1090  body += "\t}\n";
1091  body += "\tPy_XDECREF(global_dict);\n";
1092  body += "\treturn outputEnum;\n";
1093  body += "}\n\n";
1094 
1095  body += "///Allocate the "+className+"\n";
1096  body += "/**\t@param type : type variable\n";
1097  body += " * \t@param args : args variable\n";
1098  body += " * \t@param kwds : kwds variable\n";
1099  body += " * \t@return object to be allocated\n";
1100  body += "*/\n";
1101  body += "PyObject * "+className+"_newC(PyTypeObject * type, PyObject * args, PyObject * kwds){\n";
1102  body += "\t//Here, we will use a very ugly trick but since we are doing python nobody will notice\n";
1103  body += "\tPyObject* outputEnum = "+className+"_newGeneric(\"\", \""+pythonClassName+"\");\n";
1104  body += "\treturn outputEnum;\n";
1105  body += "}\n\n";
1106 
1107  body += "///Allocate the "+className+"\n";
1108  body += "/**\t@param type : type variable\n";
1109  body += " * \t@param args : args variable\n";
1110  body += " * \t@param kwds : kwds variable\n";
1111  body += " * \t@return object to be allocated\n";
1112  body += "*/\n";
1113  body += "PyObject * "+className+"_newAttributeC(){\n";
1114  body += "\t//Here, we will use a very ugly trick but since we are doing python nobody will notice\n";
1115  body += "\tPyObject* outputEnum = "+className+"_newGeneric(\"_var_______ = "+pythonClassName+"."+vecAttr.front().getName()+"\\n\\n\", \"_var_______\");\n";
1116  body += "\treturn outputEnum;\n";
1117  body += "}\n\n";
1118  return body;
1119 }
1120 
1121 
1123 
1127 PString project_wrapper_enumImpl(const PClassConfig & classConfig, const PString & moduleName){
1128  PString body, className("WP"+classConfig.getName());
1129  body += "const std::map<int, std::string> "+className+"EnumValue = {\n";
1130  body += "\t";
1131  PString comma("");
1132  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
1133  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
1134  body += comma;
1135  body += "{"+it->getDefaultValue()+", \""+it->getName()+"\"}";
1136  comma = ",\n\t";
1137  }
1138  body += "\n};\n\n";
1139 
1140 // body += "///Getters and setters of the class "+className+"\n";
1141 // body += "PyGetSetDef "+className+"_getseters[] = {\n";
1142 // //Only for complex types
1143 // const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
1144 // for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
1145 // body += "\t{(char*)\""+it->getName()+"\", (getter)"+className+"_get"+it->getName()+", (setter)"+className+"_set"+it->getName()+", (char*)\""+it->getDocumentation().replace("///", "")+"\", NULL},\n";
1146 // }
1147 // body += "\t{NULL} /* Sentinel */\n";
1148 // body += "};\n\n";
1149 // body += "///Members of class "+className+"\n";
1150 // body += "PyMemberDef "+className+"_members[] = {\n";
1151 // body += "\t{NULL} /* Sentinel */\n";
1152 // body += "};\n\n";
1153 // body += "///Methods of class "+className+"\n";
1154 // body += "PyMethodDef "+className+"_methods[] = {\n";
1155 // body += "\t{\"getTypeName\", (PyCFunction)"+className+"_getTypeName, METH_NOARGS | METH_STATIC, \"Doc : Get the type name of "+className+" for TypeStream compatibility\"},\n";
1156 // body += "\t{\"fromBytes\", (PyCFunction)"+className+"_fromBytes, METH_VARARGS, \"Doc : load a "+className+" from PyByteArray\"},\n";
1157 // body += "\t{\"toBytes\", (PyCFunction)"+className+"_toBytes, METH_NOARGS, \"Doc : convert a "+className+" to PyByteArray\"},\n";
1158 // body += "\t{\"getSize\", (PyCFunction)"+className+"_getSizeInByte, METH_NOARGS, \"Doc : Get the size of "+className+" in bytes\"},\n";
1159 
1160  //We have to put methods for DataStream and TypeStream here
1161 // body += "\t{NULL, NULL} /* Sentinel */\n";
1162 // body += "};\n\n";
1163 // body += project_wrapper_enumImplPythonType(classConfig, moduleName, "&PyEnum_Type");
1164 // body += "///Get the type name of "+className+" for TypeStream compatibility\n";
1165 // body += "/**\t@return type name of "+className+"\n";
1166 // body += "*/\n";
1167 // body += "PyObject * "+className+"_getTypeName(PyObject *self, PyObject *args){\n";
1168 // body += "\tstd::string name(\""+classConfig.getName()+"\");\n";
1169 // body += "\treturn Py_BuildValue(\"s\", name.c_str());\n";
1170 // body += "}\n\n";
1171 
1172  body += project_wrapper_enumImplNewc(classConfig);
1173 // body += project_wrapper_classImplDealloc(classConfig);
1174 // body += project_wrapper_classImplGetterSetter(classConfig);
1175 
1176  return body;
1177 }
1178 
1180 
1184 PString project_wrapper_classImpl(const PClassConfig & classConfig, const PString & moduleName){
1185  PString body, className("WP"+classConfig.getName());
1186  body += "///Getters and setters of the class "+className+"\n";
1187  body += "PyGetSetDef "+className+"_getseters[] = {\n";
1188  //Only for complex types
1189  const std::vector<PClassAttribute> & vecAttr = classConfig.getListAttribute();
1190  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
1191  if(getIsSimpleType(it->getType())){
1192  continue;
1193  }
1194  body += "\t{(char*)\""+it->getName()+"\", (getter)"+className+"_get"+it->getName()+", (setter)"+className+"_set"+it->getName()+", (char*)\""+it->getDocumentation().replace("///", "")+"\", NULL},\n";
1195  }
1196 
1197  body += "\t{NULL} /* Sentinel */\n";
1198  body += "};\n\n";
1199 
1200  //Only for simple types
1201  body += "///Members of class "+className+"\n";
1202  body += "PyMemberDef "+className+"_members[] = {\n";
1203  for(std::vector<PClassAttribute>::const_iterator it(vecAttr.begin()); it != vecAttr.end(); ++it){
1204  if(!getIsSimpleType(it->getType())){
1205  continue;
1206  }
1207  body += "\t{(char*)\""+it->getName()+"\", "+getPythonStrForPythonApiType(it->getType())+", offsetof("+className+", "+it->getName()+"), 0, (char*)\"Doc : "+it->getDocumentation().replace("///", "")+"\"},\n";
1208  }
1209  body += "\t{NULL} /* Sentinel */\n";
1210  body += "};\n\n";
1211 // METH_VARARGS
1212  body += "///Methods of class "+className+"\n";
1213  body += "PyMethodDef "+className+"_methods[] = {\n";
1214  body += "\t{\"getTypeName\", (PyCFunction)"+className+"_getTypeName, METH_NOARGS | METH_STATIC, \"Doc : Get the type name of "+className+" for TypeStream compatibility\"},\n";
1215  body += "\t{\"fromBytes\", (PyCFunction)"+className+"_fromBytes, METH_VARARGS, \"Doc : load a "+className+" from PyByteArray\"},\n";
1216  body += "\t{\"toBytes\", (PyCFunction)"+className+"_toBytes, METH_NOARGS, \"Doc : convert a "+className+" to PyByteArray\"},\n";
1217  body += "\t{\"getSize\", (PyCFunction)"+className+"_getSizeInByte, METH_NOARGS, \"Doc : Get the size of "+className+" in bytes\"},\n";
1218 
1219  //We have to put methods for DataStream and TypeStream here
1220  body += "\t{NULL, NULL} /* Sentinel */\n";
1221  body += "};\n\n";
1222 
1223  body += project_wrapper_classImplPythonType(classConfig, moduleName, "NULL");
1224  body += project_wrapper_classImplCheck(classConfig, moduleName);
1225 
1226  body += "///Get the type name of "+className+" for TypeStream compatibility\n";
1227  body += "/**\t@return type name of "+className+"\n";
1228  body += "*/\n";
1229  body += "PyObject * "+className+"_getTypeName(PyObject *self, PyObject *args){\n";
1230  body += "\tstd::string name(\""+classConfig.getName()+"\");\n";
1231  body += "\treturn Py_BuildValue(\"s\", name.c_str());\n";
1232  body += "}\n\n";
1233 
1234  body += project_wrapper_classImplNewc(classConfig);
1235  body += project_wrapper_classImplDealloc(classConfig);
1236  body += project_wrapper_classImplGetterSetter(classConfig);
1237  body += project_wrapper_dataStreamMethod(classConfig, className);
1238 
1239  return body;
1240 }
1241 
1243 
1247 PString project_wrapper_allClassImpl(const std::vector<PClassConfig> & vecClassConfig, const PString & moduleName){
1248  PString body;
1249  for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
1250  if(it->getIsEnum()){
1251  body += project_wrapper_enumImpl(*it, moduleName);
1252  }else{
1253  body += project_wrapper_classImpl(*it, moduleName);
1254  }
1255  }
1256  return body;
1257 }
1258 
1260 
1267 bool project_wrapper_moduleGeneratorWrapperImpl(const PPath & wrapperSource, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
1268  PString body;
1269  body += licenceSaveStr();
1270  body += "\n";
1271 
1272  body += "#define NO_IMPORT_ARRAY\n";
1273 
1274  body += "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\n";
1275  body += "#ifndef DISABLE_COOL_ARRAY\n";
1276  body += "#\tdefine PY_ARRAY_UNIQUE_SYMBOL "+baseImplInclude.toLower()+"_ARRAY_API\n";
1277  body += "#endif\n";
1278 // body += "#include \"numpy/ndarraytypes.h\"\n";
1279  body += "#include \"numpy/arrayobject.h\"\n";
1280  body += "#include \""+ baseImplInclude + "_wrapper.h\"\n";
1281  body += "\n";
1282  body += project_wrapper_allClassImpl(vecClassConfig, "py"+projectConfig.name.toLower());
1283  body += "\n";
1284 
1285  return wrapperSource.saveFileContent(body);
1286 }
1287 
1289 
1296 bool project_wrapper_moduleGenerator(const PPath & modulePath, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
1297  PPath mainModuleFile(modulePath / PPath(projectConfig.name.toLower() + "_module.cpp"));
1298  if(!project_wrapper_moduleGeneratorMain(mainModuleFile, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
1299  //TODO : Need to save the class definition, with struct, type, getter, setter, method to get the name of the type in TypeStream, magic with DataStream to avoid data copy
1300 
1301  PPath wrapperHeader(modulePath / PPath(baseImplInclude + "_wrapper.h"));
1302  if(!project_wrapper_moduleGeneratorWrapperHeader(wrapperHeader, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
1303 
1304  PPath wrapperSource(modulePath / PPath(baseImplInclude + "_wrapper.cpp"));
1305  if(!project_wrapper_moduleGeneratorWrapperImpl(wrapperSource, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
1306 
1307  return true;
1308 }
1309 
1310 
std::vector< PPath > PVecPath
Definition: PPath.h:75
Describes a class attribute.
const PString & getDocumentation() const
Gets the documentation of the PClassAttribute.
const PString & getType() const
Gets the type of the PClassAttribute.
bool getIsEnum() const
Gets the isEnum of the PClassAttribute.
const PString & getName() const
Gets the name of the PClassAttribute.
Class to describe a basic class.
Definition: PClassConfig.h:14
const PString & getClassDocumentation() const
Returns the class documentation.
const std::vector< PClassAttribute > & getListAttribute() const
Returns the list of attributes of the class.
const PString & getName() const
Returns the class name.
Path of a directory or a file.
Definition: PPath.h:17
bool saveFileContent(const PString &content) const
Save a PString in a file.
Definition: PPath.cpp:395
Extends the std::string.
Definition: PString.h:16
PString replace(const PString &pattern, const PString &replaceStr) const
Replace a PString into an other PString.
Definition: PString.cpp:204
PString toLower() const
Convert PString in lower case.
Definition: PString.cpp:598
PString toUpper() const
Convert std::string in upper case.
Definition: PString.cpp:639
PString licenceSaveStr()
Get the licence in string.
bool getIsSimpleType(const PString &varType)
Check if the given type is a simple type.
Configuration of the project.
PString name
Name of the project.
PString generator_getListNestedType(const PString &type)
Get the nested type inside a std::list.
Definition: type_utils.cpp:22
bool generator_typeIsList(const PString &type)
Say if a given type is a std::list.
Definition: type_utils.cpp:14
PString getPythonStrForPythonApiType(const PString &typeStr)
Gets the python API str type of the correcponding numpy C/C++ type.
PString project_wrapper_classImplPythonType(const PClassConfig &classConfig, const PString &moduleName, const PString &fromOtherType)
Create the Python type of the given class.
PString project_wrapper_classAttributeToMessage(const PString &className, const PClassAttribute &attr)
Do the implementation of to message of one attribute.
PString project_wrapper_moduleGeneratorWrapperHeaderStructDef(const PClassConfig &classConfig)
Struct of the wrapper.
PString projecy_wrapper_classCheckCall(const PString &className, const PString &functionName)
Call the check of a class.
PString project_wrapper_classAttributeFromMessage(const PString &className, const PClassAttribute &attr)
Do the implementation of from message of one attribute.
PString project_wrapper_classPythonFromBytes(const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _fromBytes for one class.
PString project_wrapper_enumImplPythonType(const PClassConfig &classConfig, const PString &moduleName, const PString &fromOtherType)
Create the Python type of the given class.
PString project_wrapper_classImplNewc(const PClassConfig &classConfig)
Implement new and dealloc.
PString project_wrapper_moduleGeneratorWrapperHeaderEnumDef(const PClassConfig &classConfig)
Enum of the wrapper.
PString wrapper_getExpectedType(const PString &type)
Get the expected type of a given python type.
PString project_wrapper_classImpl(const PClassConfig &classConfig, const PString &moduleName)
Do the implementation of one classe.
bool project_wrapper_moduleGeneratorWrapperImpl(const PPath &wrapperSource, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the wrapper module source.
PString wrapper_getObjectToValue(const PString &type)
Get the function to convert the given object to a value.
PString project_wrapper_attributeDef(const PClassAttribute &attr)
Get the C++ definition of an attribute.
PString project_wrapper_dataStreamMethod(const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method for one class.
PString project_wrapper_classPythonGetSizeInBytes(const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _getSizeInByte for one class.
PString wrapper_getBuildValueStr(const PString &type)
Get the string description of the Py_BuildValue call for the given type.
PString project_wrapper_classPythonToBytes(const PClassConfig &classConfig, const PString &className)
Do the implementation of data stream method _toBytes for one class.
PString project_wrapper_enumImplNewc(const PClassConfig &classConfig)
Implement new and dealloc.
PString project_wrapper_classImplCheck(const PClassConfig &classConfig, const PString &moduleName)
Do the check implementation of class.
PString project_wrapper_classImplDealloc(const PClassConfig &classConfig)
Implement new and dealloc.
PString project_wrapper_allClassImpl(const std::vector< PClassConfig > &vecClassConfig, const PString &moduleName)
Do the implementation of all classes.
PString project_wrapper_enumImpl(const PClassConfig &classConfig, const PString &moduleName)
Do the implementation of one enum.
PString project_wrapper_callAttributeCheck(const PString &className, const PClassAttribute &attr, const PString &moduleName, const PString &expectedType)
Do the check call of an attribute of a given class.
bool project_wrapper_moduleGeneratorWrapperHeader(const PPath &wrapperHeader, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the wrapper module header.
PString project_wrapper_modulePyTypeReady(const std::vector< PClassConfig > &vecClassConfig)
Create the PyType_Ready for all classes of the module.
bool project_wrapper_moduleGenerator(const PPath &modulePath, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the wrapper module.
PString project_wrapper_modulePyIncref(const std::vector< PClassConfig > &vecClassConfig)
Create the Py_INCREF for all classes of the module.
PString project_wrapper_moduleAddObject(const std::vector< PClassConfig > &vecClassConfig)
Create the Py_INCREF for all classes of the module.
PString wrapper_getValueToObject(const PString &type)
Get the function to convert the given value to a PyObject.
PString project_wrapper_classGetterSetterDef(const PString &className, const PClassAttribute &attr)
Definition of the getter and setter for complex types.
bool project_wrapper_moduleGeneratorMain(const PPath &fileName, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the main wrapper module.
PString getObjectParseTuple(const PString &varName)
Get the proper code for PyArg_ParseTuple with one object.
PString project_wrapper_classAttributeGetSize(const PString &className, const PClassAttribute &attr)
Do the implementation of get size of one attribute.
PString project_wrapper_classImplGetterSetter(const PClassConfig &classConfig)
Implement new and dealloc.
PString project_wrapper_moduleGeneratorWrapperHeaderAllStructDef(const std::vector< PClassConfig > &vecClassConfig)
Predefine struct of the wrapper.
PString project_wrapper_moduleGeneratorWrapperHeaderStructPreDef(const std::vector< PClassConfig > &vecClassConfig)
Predefine struct of the wrapper.