support dynamic cast from all parents/virtual base

release/4.3a0
Duy-Nguyen Ta 2016-11-18 11:00:15 -05:00
parent 39f4d92061
commit 9f58d21030
4 changed files with 49 additions and 6 deletions

View File

@ -1,6 +1,5 @@
TODO: TODO:
☐ Casting from parent and grandparents
☐ Allow overloading methods. The current solution is annoying!!! ☐ Allow overloading methods. The current solution is annoying!!!
☐ forward declaration? ☐ forward declaration?
☐ Global functions ☐ Global functions
@ -12,6 +11,7 @@ TODO:
☐ CMake install script ☐ CMake install script
Completed/Cancelled: Completed/Cancelled:
✔ Casting from parent and grandparents
✔ Allow overloading constructors. The current solution is annoying!!! @done (16-11-16 17:00) ✔ Allow overloading constructors. The current solution is annoying!!! @done (16-11-16 17:00)
✔ Support "print obj" @done (16-11-16 17:00) ✔ Support "print obj" @done (16-11-16 17:00)
✔ methods for FastVector: at, [], ... @done (16-11-16 17:00) ✔ methods for FastVector: at, [], ... @done (16-11-16 17:00)

View File

@ -770,8 +770,8 @@ void Class::pyxInitParentObj(FileWriter& pyxFile, const std::string& pyObj,
pyxFile.oss << pyObj << "." << parentClass->pyxCythonObj() << " = " pyxFile.oss << pyObj << "." << parentClass->pyxCythonObj() << " = "
<< "<" << parentClass->pyxSharedCythonClass() << ">(" << "<" << parentClass->pyxSharedCythonClass() << ">("
<< cySharedObj << ")\n"; << cySharedObj << ")\n";
// Find the parent class with name "parentClass" and point its cython obj to the same pointer // Find the parent class with name "parentClass" and point its cython obj
// TODO: This search is not efficient. :-( // to the same pointer
auto parent_it = find_if(allClasses.begin(), allClasses.end(), auto parent_it = find_if(allClasses.begin(), allClasses.end(),
[this](const Class& cls) { [this](const Class& cls) {
return cls.cythonClass() == return cls.cythonClass() ==
@ -785,6 +785,42 @@ void Class::pyxInitParentObj(FileWriter& pyxFile, const std::string& pyObj,
} }
} }
/* ************************************************************************* */
/*
@staticmethod
def dynamic_cast(noiseModel_Base base):
cdef noiseModel_Gaussian ret = noiseModel_Gaussian()
ret.gtnoiseModel_Gaussian_ = <shared_ptr[gtsam.noiseModel_Gaussian]>dynamic_pointer_cast[gtsam.noiseModel_Gaussian, gtsam.noiseModel_Base](base.gtnoiseModel_Base_)
ret.gtnoiseModel_Base_ = <shared_ptr[gtsam.noiseModel_Base]>(ret.gtnoiseModel_Gaussian_)
return ret
*/
void Class::pyxDynamicCast(FileWriter& pyxFile, const Class& curLevel,
const std::vector<Class>& allClasses) const {
std::string me = this->pythonClass(), sharedMe = this->pyxSharedCythonClass();
if (curLevel.parentClass) {
std::string parent = curLevel.parentClass->pythonClass(),
parentObj = curLevel.parentClass->pyxCythonObj(),
parentCythonClass = curLevel.parentClass->pyxCythonClass();
pyxFile.oss << "def dynamic_cast_" << me << "_" << parent << "(" << parent
<< " parent):\n";
pyxFile.oss << "\treturn " << me << ".cyCreateFromShared(<" << sharedMe
<< ">dynamic_pointer_cast[" << pyxCythonClass() << ","
<< parentCythonClass << "](parent." << parentObj
<< "))\n";
// Move up higher to one level: Find the parent class with name "parentClass"
auto parent_it = find_if(allClasses.begin(), allClasses.end(),
[&curLevel](const Class& cls) {
return cls.cythonClass() ==
curLevel.parentClass->cythonClass();
});
if (parent_it == allClasses.end()) {
cerr << "Can't find parent class: " << parentClass->cythonClass();
throw std::runtime_error("Parent class not found!");
}
pyxDynamicCast(pyxFile, *parent_it, allClasses);
}
}
/* ************************************************************************* */ /* ************************************************************************* */
void Class::emit_cython_pyx(FileWriter& pyxFile, const std::vector<Class>& allClasses) const { void Class::emit_cython_pyx(FileWriter& pyxFile, const std::vector<Class>& allClasses) const {
pyxFile.oss << "cdef class " << pythonClass(); pyxFile.oss << "cdef class " << pythonClass();
@ -853,6 +889,9 @@ void Class::emit_cython_pyx(FileWriter& pyxFile, const std::vector<Class>& allCl
for(const Method& m: methods_ | boost::adaptors::map_values) for(const Method& m: methods_ | boost::adaptors::map_values)
m.emit_cython_pyx(pyxFile, *this); m.emit_cython_pyx(pyxFile, *this);
pyxDynamicCast(pyxFile, *this, allClasses);
pyxFile.oss << "\n\n"; pyxFile.oss << "\n\n";
} }

View File

@ -160,6 +160,8 @@ public:
void pyxInitParentObj(FileWriter& pyxFile, const std::string& pyObj, void pyxInitParentObj(FileWriter& pyxFile, const std::string& pyObj,
const std::string& cySharedObj, const std::string& cySharedObj,
const std::vector<Class>& allClasses) const; const std::vector<Class>& allClasses) const;
void pyxDynamicCast(FileWriter& pyxFile, const Class& curLevel,
const std::vector<Class>& allClasses) const;
friend std::ostream& operator<<(std::ostream& os, const Class& cls) { friend std::ostream& operator<<(std::ostream& os, const Class& cls) {
os << "class " << cls.name() << "{\n"; os << "class " << cls.name() << "{\n";

View File

@ -338,7 +338,8 @@ void Module::emit_cython_pxd(FileWriter& pxdFile) const {
"\t\tshared_ptr()\n" "\t\tshared_ptr()\n"
"\t\tshared_ptr(T*)\n" "\t\tshared_ptr(T*)\n"
"\t\tT* get()\n" "\t\tT* get()\n"
"\t\tT& operator*()\n\n"; "\t\tT& operator*()\n\n"
"\tcdef shared_ptr[T] dynamic_pointer_cast[T,U](const shared_ptr[U]& r)\n";
for(const TypedefPair& types: typedefs) for(const TypedefPair& types: typedefs)
types.emit_cython_pxd(pxdFile); types.emit_cython_pxd(pxdFile);
@ -366,13 +367,14 @@ void Module::emit_cython_pxd(FileWriter& pxdFile) const {
pxdFile.emit(true); pxdFile.emit(true);
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Module::emit_cython_pyx(FileWriter& pyxFile) const { void Module::emit_cython_pyx(FileWriter& pyxFile) const {
// headers... // headers...
string pxdHeader = name + "_wrapper"; string pxdHeader = name + "_wrapper";
pyxFile.oss << "cimport numpy as np\n" pyxFile.oss << "cimport numpy as np\n"
"cimport " << pxdHeader << " as " << name << "\n" "cimport " << pxdHeader << " as " << name << "\n"
"from "<< pxdHeader << " cimport shared_ptr\n"; "from "<< pxdHeader << " cimport shared_ptr\n"
"from "<< pxdHeader << " cimport dynamic_pointer_cast\n";
// import all typedefs, e.g. from gtsam cimport Key, so we don't need to say gtsam.Key // import all typedefs, e.g. from gtsam cimport Key, so we don't need to say gtsam.Key
for(const Qualified& q: Qualified::BasicTypedefs) { for(const Qualified& q: Qualified::BasicTypedefs) {
pyxFile.oss << "from " << pxdHeader << " cimport " << q.cythonClass() << "\n"; pyxFile.oss << "from " << pxdHeader << " cimport " << q.cythonClass() << "\n";