import textwrap class WrapperTemplate: """Class to encapsulate string templates for use in wrapper generation""" boost_headers = textwrap.dedent(""" #include #include #include """) typdef_collectors = textwrap.dedent('''\ typedef std::set*> Collector_{class_name}; static Collector_{class_name} collector_{class_name}; ''') delete_obj = textwrap.indent(textwrap.dedent('''\ {{ for(Collector_{class_name}::iterator iter = collector_{class_name}.begin(); iter != collector_{class_name}.end(); ) {{ delete *iter; collector_{class_name}.erase(iter++); anyDeleted = true; }} }} '''), prefix=' ') delete_all_objects = textwrap.dedent(''' void _deleteAllObjects() {{ mstream mout; std::streambuf *outbuf = std::cout.rdbuf(&mout);\n bool anyDeleted = false; {delete_objs} if(anyDeleted) cout << "WARNING: Wrap modules with variables in the workspace have been reloaded due to\\n" "calling destructors, call \'clear all\' again if you plan to now recompile a wrap\\n" "module, so that your recompiled module is used instead of the old one." << endl; std::cout.rdbuf(outbuf); }} ''') rtti_register = textwrap.dedent('''\ void _{module_name}_RTTIRegister() {{ const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_{module_name}_rttiRegistry_created"); if(!alreadyCreated) {{ std::map types; {rtti_classes} mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); if(!registry) registry = mxCreateStructMatrix(1, 1, 0, NULL); typedef std::pair StringPair; for(const StringPair& rtti_matlab: types) {{ int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); if(fieldId < 0) {{ mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); }} mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxSetFieldByNumber(registry, 0, fieldId, matlabName); }} if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {{ mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); }} mxDestroyArray(registry); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {{ mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); }} mxDestroyArray(newAlreadyCreated); }} }} ''') collector_function_upcast_from_void = textwrap.dedent('''\ void {class_name}_upcastFromVoid_{id}(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {{ mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr<{cpp_name}> Shared; boost::shared_ptr *asVoid = *reinterpret_cast**> (mxGetData(in[0])); out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); Shared *self = new Shared(boost::static_pointer_cast<{cpp_name}>(*asVoid)); *reinterpret_cast(mxGetData(out[0])) = self; }}\n ''') class_serialize_method = textwrap.dedent('''\ function varargout = string_serialize(this, varargin) % STRING_SERIALIZE usage: string_serialize() : returns string % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 0 varargout{{1}} = {wrapper}({wrapper_id}, this, varargin{{:}}); else error('Arguments do not match any overload of function {class_name}.string_serialize'); end end\n function sobj = saveobj(obj) % SAVEOBJ Saves the object to a matlab-readable format sobj = obj.string_serialize(); end ''') collector_function_serialize = textwrap.indent(textwrap.dedent("""\ typedef boost::shared_ptr<{full_name}> Shared; checkArguments("string_serialize",nargout,nargin-1,0); Shared obj = unwrap_shared_ptr<{full_name}>(in[0], "ptr_{namespace}{class_name}"); ostringstream out_archive_stream; boost::archive::text_oarchive out_archive(out_archive_stream); out_archive << *obj; out[0] = wrap< string >(out_archive_stream.str()); """), prefix=' ') collector_function_deserialize = textwrap.indent(textwrap.dedent("""\ typedef boost::shared_ptr<{full_name}> Shared; checkArguments("{namespace}{class_name}.string_deserialize",nargout,nargin,1); string serialized = unwrap< string >(in[0]); istringstream in_archive_stream(serialized); boost::archive::text_iarchive in_archive(in_archive_stream); Shared output(new {full_name}()); in_archive >> *output; out[0] = wrap_shared_ptr(output,"{namespace}.{class_name}", false); """), prefix=' ') mex_function = textwrap.dedent(''' void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {{ mstream mout; std::streambuf *outbuf = std::cout.rdbuf(&mout);\n _{module_name}_RTTIRegister();\n int id = unwrap(in[0]);\n try {{ switch(id) {{ {cases} }} }} catch(const std::exception& e) {{ mexErrMsgTxt(("Exception from gtsam:\\n" + std::string(e.what()) + "\\n").c_str()); }}\n std::cout.rdbuf(outbuf); }} ''') collector_function_shared_return = textwrap.indent(textwrap.dedent('''\ {{ boost::shared_ptr<{name}> shared({shared_obj}); out[{id}] = wrap_shared_ptr(shared,"{name}"); }}{new_line}'''), prefix=' ') matlab_deserialize = textwrap.indent(textwrap.dedent("""\ function varargout = string_deserialize(varargin) % STRING_DESERIALIZE usage: string_deserialize() : returns {class_name} % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 varargout{{1}} = {wrapper}({id}, varargin{{:}}); else error('Arguments do not match any overload of function {class_name}.string_deserialize'); end end\n function obj = loadobj(sobj) % LOADOBJ Saves the object to a matlab-readable format obj = {class_name}.string_deserialize(sobj); end """), prefix=' ')