📄 define.cc
字号:
#include <limits.h>#include <string.h>#include <tcl.h>#include "assert.hh"#include "error.hh"#include "module.hh"#include "simarg.hh"#include "sulima.hh"// BasicModule constructor.BasicModule::BasicModule(const char *name) : name_str(copy(name)){ // Create the Tcl namespace. char *script = copy("namespace eval sim::", name, " { }", 0); int rc = Tcl_GlobalEval(sulima_tcl, script); delete script; if (rc != TCL_OK) throw ScriptError();}// BasicModule destructor.BasicModule::~BasicModule(){ delete name_str;}// Define a Tcl variable.static voiddefine(const char *ns, const char *name, void *addr, int type, bool ro){ if (ro) type |= TCL_LINK_READ_ONLY; char *full_name = !strcmp(ns, "Sulima") ? copy("::sim::", name, 0) : copy("::sim::", ns, "::", name, 0); int rc = Tcl_LinkVar(sulima_tcl, full_name, (char *)addr, type); delete full_name; if (rc != TCL_OK) throw ScriptError();}voidBasicModule::define(const char *nm, int &var, int init, bool ro){ var = init; ::define(name(), nm, &var, TCL_LINK_INT, ro);}voidBasicModule::define(const char *nm, char *&var, const char *init, bool ro){ size_t n = strlen(init) + 1; var = Tcl_Alloc(n); if (!var) throw OutOfMemory(); memcpy(var, init, n); try { ::define(name(), nm, &var, TCL_LINK_STRING, ro); } catch (...) { Tcl_Free(var); throw; }}// Create a new Tcl function from a global C++ function. The user-supplied// function is enclosed in a simple C wrappers to mould the arguments and// return values into shape.struct PlainWrapper { SimArg (*fn)(const SimArgs &); PlainWrapper(SimArg (*f)(const SimArgs &)) : fn(f) { }};extern "C" { static int plain_wrapper(PlainWrapper *p, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { try { SimArg ret = p->fn(SimArgs(objc - 1, objv + 1)); Tcl_SetObjResult(interp, ret.get_obj()); return TCL_OK; } catch (const Error &e) { Tcl_SetResult(interp, (char *)e.what(), TCL_VOLATILE); return TCL_ERROR; } } static void delete_plain_wrapper(PlainWrapper *p) { delete p; }}voidBasicModule::define(const char *nm, SimArg (*fn)(const SimArgs &)){ PlainWrapper *wrapper = new PlainWrapper(fn); char *full_name = !strcmp(name(), "Sulima") ? copy("::sim::", nm, 0) : copy("::sim::", name(), "::", nm, 0); Tcl_Command rc = Tcl_CreateObjCommand(sulima_tcl, full_name, (Tcl_ObjCmdProc *)plain_wrapper, (ClientData)wrapper, (Tcl_CmdDeleteProc *)delete_plain_wrapper); delete full_name; if (!rc) throw ScriptError();}// Create a new Tcl function from a C++ member function. The user-supplied// function is enclosed in a simple C wrappers to mould the arguments and// return values into shape.struct MemberWrapper { Object *obj; SimArg (Object::*fn)(const SimArgs &); MemberWrapper(Object *o, SimArg (Object::*f)(const SimArgs &)) : obj(o), fn(f) { }};extern "C" { static int member_wrapper(MemberWrapper *p, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { try { SimArg ret = ((p->obj)->*(p->fn))(SimArgs(objc - 1, objv + 1)); Tcl_SetObjResult(interp, ret.get_obj()); return TCL_OK; } catch (const Error &e) { Tcl_SetResult(interp, (char *)e.what(), TCL_VOLATILE); return TCL_ERROR; } } static void delete_member_wrapper(MemberWrapper *p) { delete p; }}voidBasicModule::define(const char *nm, Object *obj, SimArg (Object::*fn)(const SimArgs &)){ MemberWrapper *wrapper = new MemberWrapper(obj, fn); char *full_name = !strcmp(name(), "Sulima") ? copy("::sim::", nm, 0) : copy("::sim::", name(), "::", nm, 0); Tcl_Command rc = Tcl_CreateObjCommand(sulima_tcl, full_name, (Tcl_ObjCmdProc *)member_wrapper, (ClientData)wrapper, (Tcl_CmdDeleteProc *)delete_member_wrapper); delete full_name; if (!rc) { delete wrapper; throw ScriptError(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -