diff --git a/gtsam.h b/gtsam.h index cc78038b6..35def3b76 100644 --- a/gtsam.h +++ b/gtsam.h @@ -470,6 +470,9 @@ virtual class Pose2 : gtsam::Value { gtsam::Point2 translation() const; gtsam::Rot2 rotation() const; Matrix matrix() const; + + // enabling serialization functionality + void serialize() const; }; virtual class Pose3 : gtsam::Value { diff --git a/wrap/Class.cpp b/wrap/Class.cpp index 6586fb061..bed5de9bb 100644 --- a/wrap/Class.cpp +++ b/wrap/Class.cpp @@ -124,6 +124,10 @@ void Class::matlab_proxy(const string& toolboxPath, const string& wrapperName, wrapperFile.oss << "\n"; } + // Add serialization if necessary + if (isSerializable) + serialization_fragments(proxyFile, wrapperFile, functionNames); + proxyFile.oss << " end\n"; proxyFile.oss << "end\n"; @@ -278,6 +282,7 @@ Class expandClassTemplate(const Class& cls, const string& templateArg, const vec inst.templateArgs = cls.templateArgs; inst.typedefName = cls.typedefName; inst.isVirtual = cls.isVirtual; + inst.isSerializable = cls.isSerializable; inst.qualifiedParent = cls.qualifiedParent; inst.methods = expandMethodTemplate(cls.methods, templateArg, instName, expandedClassNamespace, expandedClassName); inst.static_methods = expandMethodTemplate(cls.static_methods, templateArg, instName, expandedClassNamespace, expandedClassName); @@ -388,6 +393,38 @@ void Class::comment_fragment(FileWriter& proxyFile) const { } } + if (isSerializable) { + proxyFile.oss << "%\n%-------Serialization Interface-------\n"; + proxyFile.oss << "%string_serialize() : returns string\n"; + proxyFile.oss << "%string_deserialize(string serialized) : returns " << this->name << "\n"; + } + proxyFile.oss << "%\n"; } /* ************************************************************************* */ + +void Class::serialization_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, std::vector& functionNames) const { +//void Point3_string_serialize_17(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +//{ +// typedef boost::shared_ptr Shared; +// checkArguments("string_serialize",nargout,nargin-1,0); +// Shared obj = unwrap_shared_ptr(in[0], "ptr_Point3"); +// std::ostringstream out_archive_stream; +// boost::archive::text_oarchive out_archive(out_archive_stream); +// out_archive << *obj; +// out[0] = wrap< string >(out_archive_stream.str()); +//} +// +//void Point3_string_deserialize_18(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +//{ +// typedef boost::shared_ptr Shared; +// checkArguments("Point3.string_deserialize",nargout,nargin,1); +// string serialized = unwrap< string >(in[0]); +// std::istringstream in_archive_stream(serialized); +// boost::archive::text_iarchive in_archive(in_archive_stream); +// Shared output(new Point3()); +// in_archive >> output; +// out[0] = wrap_shared_ptr(output,"Point3", false); +//} + +} diff --git a/wrap/Class.h b/wrap/Class.h index 5c04bd609..d66d805b9 100644 --- a/wrap/Class.h +++ b/wrap/Class.h @@ -56,14 +56,17 @@ struct Class { // And finally MATLAB code is emitted, methods below called by Module::matlab_code void matlab_proxy(const std::string& toolboxPath, const std::string& wrapperName, const TypeAttributesTable& typeAttributes, FileWriter& wrapperFile, std::vector& functionNames) const; ///< emit proxy class + std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter std::vector expandTemplate(const std::string& templateArg, const std::vector >& instantiations) const; + Class expandTemplate(const std::string& templateArg, const std::vector& instantiation, const std::vector& expandedClassNamespace, const std::string& expandedClassName) const; // The typedef line for this class, if this class is a typedef, otherwise returns an empty string. std::string getTypedef() const; + void serialization_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, std::vector& functionNames) const; private: void pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const std::string& wrapperName, std::vector& functionNames) const; diff --git a/wrap/Module.cpp b/wrap/Module.cpp index 02c1787b7..ec346a7a0 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -448,16 +448,6 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co fs::create_directories(toolboxPath); - // create the unified .cpp switch file - const string wrapperName = name + "_wrapper"; - string wrapperFileName = toolboxPath + "/" + wrapperName + ".cpp"; - FileWriter wrapperFile(wrapperFileName, verbose, "//"); - vector functionNames; // Function names stored by index for switch - wrapperFile.oss << "#include \n"; - wrapperFile.oss << "#include \n"; - wrapperFile.oss << "#include \n"; - wrapperFile.oss << "\n"; - // Expand templates - This is done first so that template instantiations are // counted in the list of valid types, have their attributes and dependencies // checked, etc. @@ -470,7 +460,9 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co verifyArguments(validTypes, global_functions); verifyReturnTypes(validTypes, global_functions); + bool hasSerialiable = false; BOOST_FOREACH(const Class& cls, expandedClasses) { + hasSerialiable |= cls.isSerializable; // verify all of the function arguments //TODO:verifyArguments(validTypes, cls.constructor.args_list); verifyArguments(validTypes, cls.static_methods); @@ -483,7 +475,6 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co // verify parents if(!cls.qualifiedParent.empty() && std::find(validTypes.begin(), validTypes.end(), wrap::qualifiedName("::", cls.qualifiedParent)) == validTypes.end()) throw DependencyMissing(wrap::qualifiedName("::", cls.qualifiedParent), cls.qualifiedName("::")); - } // Create type attributes table and check validity @@ -492,7 +483,20 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co typeAttributes.addForwardDeclarations(forward_declarations); typeAttributes.checkValidity(expandedClasses); + // create the unified .cpp switch file + const string wrapperName = name + "_wrapper"; + string wrapperFileName = toolboxPath + "/" + wrapperName + ".cpp"; + FileWriter wrapperFile(wrapperFileName, verbose, "//"); + wrapperFile.oss << "#include \n"; + wrapperFile.oss << "#include \n"; + wrapperFile.oss << "#include \n"; + wrapperFile.oss << "\n"; + // Generate includes while avoiding redundant includes + if (hasSerialiable) { + wrapperFile.oss << "#include \n"; + wrapperFile.oss << "#include \n\n"; + } generateIncludes(wrapperFile); // create typedef classes - we put this at the top of the wrap file so that collectors and method arguments can use these typedefs @@ -508,6 +512,8 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co // generate RTTI registry (for returning derived-most types) WriteRTTIRegistry(wrapperFile, name, expandedClasses); + vector functionNames; // Function names stored by index for switch + // create proxy class and wrapper code BOOST_FOREACH(const Class& cls, expandedClasses) { cls.matlab_proxy(toolboxPath, wrapperName, typeAttributes, wrapperFile, functionNames); diff --git a/wrap/tests/expected/Point3.m b/wrap/tests/expected/Point3.m index 3a90f1982..836482a7d 100644 --- a/wrap/tests/expected/Point3.m +++ b/wrap/tests/expected/Point3.m @@ -11,6 +11,9 @@ %StaticFunctionRet(double z) : returns Point3 %staticFunction() : returns double % +%-------Serialization Interface------- +%string_serialize() : returns string +%string_deserialize(string serialized) : returns Point3 classdef Point3 < handle properties ptr_Point3 = 0 @@ -48,7 +51,16 @@ classdef Point3 < handle error('Arguments do not match any overload of function Point3.norm'); end end - + + function varargout string_serialize(this, varargin) + % string_serialize usage: string_serialize() : returns string + % Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html + if length(varargin) == 0 + varargout{1} = geometry_wrapper(14, this, varargin{:}); + else + error('Arguments do not match any overload of function Point3.string_serialize'); + end + end end methods(Static = true) @@ -77,6 +89,16 @@ classdef Point3 < handle error('Arguments do not match any overload of function Point3.StaticFunction'); end end + + function varargout = string_deserialize(varargin) + % STATICFUNCTION usage: string_deserialize() : returns Point3 + % Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html + if length(varargin) == 0 + varargout{1} = geometry_wrapper(16, varargin{:}); + else + error('Arguments do not match any overload of function Point3.StaticFunction'); + end + end end end diff --git a/wrap/tests/expected/geometry_wrapper.cpp b/wrap/tests/expected/geometry_wrapper.cpp index ad1df801c..c18c2224b 100644 --- a/wrap/tests/expected/geometry_wrapper.cpp +++ b/wrap/tests/expected/geometry_wrapper.cpp @@ -2,6 +2,9 @@ #include #include +#include +#include + #include @@ -236,6 +239,29 @@ void Point3_staticFunction_16(int nargout, mxArray *out[], int nargin, const mxA out[0] = wrap< double >(Point3::staticFunction()); } +void Point3_string_serialize_17(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr Shared; + checkArguments("string_serialize",nargout,nargin-1,0); + Shared obj = unwrap_shared_ptr(in[0], "ptr_Point3"); + std::ostringstream out_archive_stream; + boost::archive::text_oarchive out_archive(out_archive_stream); + out_archive << *obj; + out[0] = wrap< string >(out_archive_stream.str()); +} + +void Point3_string_deserialize_18(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr Shared; + checkArguments("Point3.string_deserialize",nargout,nargin,1); + string serialized = unwrap< string >(in[0]); + std::istringstream in_archive_stream(serialized); + boost::archive::text_iarchive in_archive(in_archive_stream); + Shared output(new Point3()); + in_archive >> output; + out[0] = wrap_shared_ptr(output,"Point3", false); +} + void Test_collectorInsertAndMakeBase_17(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects);