PhoenixGenerator  3.4.0
Generate code from template files and projects in C++, Rust, Python and wrapped C++ to Python
Loading...
Searching...
No Matches
nanobind_generator.cpp
Go to the documentation of this file.
1/***************************************
2 Auteur : Thibaut Oprinsen, Pierre Aubert
3 Mail : thibaut.oprinsen@lapp.in2p3.fr, pierre.aubert@lapp.in2p3.fr
4 Licence : LGPL-3.0-only
5****************************************/
6
7#include <set>
8#include "header_generator.h"
10#include "phoenix_color.h"
11#include "openFileStream.h"
12
14
23bool generator_nanobind_class(const PNanobindTraitBackendManager &manager, PPath& baseFileName, const PPath &sourceFile, const PPath &headerFile, const PVecPath &extraInclude, const PVecClassConfig &vecClassConfig, const GeneratorMode &mode){
24 if(baseFileName == ""){
25 std::cerr << termRed() << "generator_class_cpp : baseFileName is empty" << termDefault() << std::endl;
26 return false;
27 }
28 std::ofstream fs;
29 if(!openFileStream(fs, sourceFile)){return false;}
30 licenceSave(fs);
31 //nanobind.h includes Python.h, which must come before any system header (it defines _POSIX_C_SOURCE/_XOPEN_SOURCE)
32 fs << std::endl << "#include <nanobind/nanobind.h>" << std::endl;
33 fs << "#include \"" << headerFile.getFileName() << "\"" << std::endl;
34 std::set<std::string> extraIncludes;
35 for (std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
36 manager.headerExtraInclude(extraIncludes, *it, mode);
37 }
38 for (const std::string & include : extraIncludes){
39 fs << include << std::endl;
40 }
41 fs << "\nnamespace nb = nanobind;" << std::endl << std::endl;
42 PString fileModuleName = baseFileName.toLower();
43 fs << "NB_MODULE(" << fileModuleName << ", m) {" << std::endl;
44 fs << "\tm.doc() = \"Nanobind bindings for " << baseFileName << " classes\";\n" << std::endl;
45
46 for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
47 if(it->getIsEnum()){
48 fs << "\tnb::enum_<" << it->getName() << "::" << it->getName() << ">(m, \"" << it->getName() << "\")" << std::endl;
49 fs << "\t\t//Values" << std::endl;
50 manager.registerProperty(fs, *it, mode);
51 manager.registerStaticMethod(fs, *it, mode);
52 manager.registerMethod(fs, *it, mode);
53 fs << ";" << std::endl << std::endl;
54 }else{
55 fs << "\tnb::class_<" << it->getName() << ">(m, \"" << it->getName() << "\")" << std::endl;
56 fs << "\t\t//Attributes" << std::endl;
57 manager.registerProperty(fs, *it, mode);
58 manager.registerConstructor(fs, *it, mode);
59 manager.registerStaticMethod(fs, *it, mode);
60
61 manager.registerMethod(fs, *it, mode);
62 fs << ";" << std::endl << std::endl;
63 }
64 }
65 fs << "}" << std::endl; // Close NB_MODULE
66 fs.close();
67 return true;
68}
69
71
79bool generator_nanobind_test(const PNanobindTraitBackendManager & manager, const PPath & outputTestDir, const std::vector<PClassConfig> & vecClassConfig, const PString & projectName, const PPath & baseFileName, const GeneratorMode & mode){
80 for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
81 PString name = it->getName();
82 PPath outputCurrentTestDir(outputTestDir + PString("/TEST_") + name.toUpper() + "_BINDINGS");
83 if(!outputCurrentTestDir.createDirectory()){
84 std::cerr << "generator_class_test : cannot create TEST directory '"<<outputCurrentTestDir<<"'" << std::endl;
85 return false;
86 }
87 std::ofstream fs;
88 if(!openFileStream(fs, PPath(outputCurrentTestDir + PString("/test_") + name + "_binding.py"))){return false;}
89 manager.headerTestInclude(fs, mode, baseFileName);
90 manager.testFunction(fs, *it, mode, baseFileName);
91 fs.close();
92 }
93 return true;
94}
95
97
101bool generator_nanobind_full(const PNanobindTraitBackendManager & manager, const ProjectParam & projectParam)
102{
103 bool b(true);
104 b &= projectParam.outputSourceDir.createDirectory();
105 b &= projectParam.outputTestDir.createDirectory();
106 const PVecDataConfig & vecDataConfig = projectParam.vecDataConfig;
107
108 for(const PDataConfig & config : vecDataConfig){
109 const PVecPath & extraInclude = config.getVecInclude();
110 PPath baseFileName = config.getFileName().getFileName().eraseExtension();
111 PPath headerFile = projectParam.outputSourceDir / PPath(baseFileName + ".h");
112 PPath sourceFile = projectParam.outputSourceDir / PPath(baseFileName + "_binding.cpp");
113 if(!generator_nanobind_class(manager, baseFileName, sourceFile, headerFile, extraInclude, config.getVecClassConfig(), projectParam.mode)){
114 std::cerr << termRed() << "generator_nanobind_full : cannot generate nanobind sources at '"<<projectParam.outputSourceDir<<"'" << termDefault() << std::endl;
115 b = false; //best effort strategy
116 }
117 PPath outputCurrentTestDir = projectParam.outputTestDir / PPath("TEST_PYTHON_BINDINGS");
118 if(!generator_nanobind_test(manager, outputCurrentTestDir, config.getVecClassConfig(), projectParam.name, baseFileName, projectParam.mode)){
119 std::cerr << termRed() << "generator_nanobind_full : cannot generate nanobind tests at '"<<projectParam.outputTestDir<<"'" << termDefault() << std::endl;
120 b = false; //best effort strategy
121 }
122 }
123 return b;
124}
std::vector< PDataConfig > PVecDataConfig
Definition PDataConfig.h:48
std::vector< PClassConfig > PVecClassConfig
Definition PDataConfig.h:14
Class to describe a basic class.
Definition PDataConfig.h:17
Manager of the Trait backends.
virtual void headerTestInclude(std::ofstream &fs, const GeneratorMode &mode, const PString &baseFileName) const
Add extra include on the test header.
virtual void registerStaticMethod(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Registration of static method.
virtual void headerExtraInclude(std::set< std::string > &setInclude, const PClassConfig &classConfig, const GeneratorMode &mode) const
Add extra include on the header.
virtual void registerProperty(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Registration of property.
virtual void testFunction(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode, const PString &baseFileName) const
Implementation of test function.
virtual void registerMethod(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Registration of method.
virtual void registerConstructor(std::ofstream &fs, const PClassConfig &classConfig, const GeneratorMode &mode) const
Registration of constructor.
void licenceSave(std::ofstream &fs)
Saves the policy.
bool generator_nanobind_test(const PNanobindTraitBackendManager &manager, const PPath &outputTestDir, const std::vector< PClassConfig > &vecClassConfig, const PString &projectName, const PPath &baseFileName, const GeneratorMode &mode)
Generate test with nanobind.
bool generator_nanobind_full(const PNanobindTraitBackendManager &manager, const ProjectParam &projectParam)
Generate the full sources and related unit tests from configuration.
bool generator_nanobind_class(const PNanobindTraitBackendManager &manager, PPath &baseFileName, const PPath &sourceFile, const PPath &headerFile, const PVecPath &extraInclude, const PVecClassConfig &vecClassConfig, const GeneratorMode &mode)
Generate nanobind wrapper class.
All the genertor modes.
Set of parameters to generate a project.
GeneratorMode mode
Mode to be used to generate the project.
PPath outputTestDir
Output path of the unit tests.
PVecDataConfig vecDataConfig
Configuration of classes to be generated.
PString name
Name of the project.
PPath outputSourceDir
Output path of the sources.