1
0
Fork 0

Reset: Nasal can be shutdown.

Also guard against duplicate init of cppbind wrapped classes.
This commit is contained in:
James Turner 2013-10-06 17:36:19 +01:00
parent 95679e6d76
commit 881df711ba
8 changed files with 124 additions and 39 deletions

View file

@ -152,17 +152,19 @@ static naRef f_createFileDialog(naContext c, naRef me, int argc, naRef* args)
void postinitNasalGUI(naRef globals, naContext c)
{
NasalFileDialog::init("gui._FileDialog")
.member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle)
.member("button", &FGFileDialog::getButton, &FGFileDialog::setButton)
.member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory)
.member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden)
.member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName)
.member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns)
.method("open", &FGFileDialog::exec)
.method("close", &FGFileDialog::close)
.method("setCallback", &FGFileDialog::setCallbackFromNasal);
if (!NasalFileDialog::isInit()) {
NasalFileDialog::init("gui._FileDialog")
.member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle)
.member("button", &FGFileDialog::getButton, &FGFileDialog::setButton)
.member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory)
.member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden)
.member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName)
.member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns)
.method("open", &FGFileDialog::exec)
.method("close", &FGFileDialog::close)
.method("setCallback", &FGFileDialog::setCallbackFromNasal);
}
nasal::Hash guiModule = nasal::Hash(globals, c).get<nasal::Hash>("gui");
guiModule.set("FILE_DIALOG_OPEN_FILE", (int) FGFileDialog::USE_OPEN_FILE);

View file

@ -204,7 +204,9 @@ naRef to_nasal_helper(naContext c, const sc::ElementWeakPtr& el)
naRef initNasalCanvas(naRef globals, naContext c)
{
NasalEvent::init("canvas.Event")
if (!NasalEvent::isInit()) {
NasalEvent::init("canvas.Event")
.member("type", &sc::Event::getTypeString)
.member("target", &sc::Event::getTarget)
.member("currentTarget", &sc::Event::getCurrentTarget)
@ -245,7 +247,8 @@ naRef initNasalCanvas(naRef globals, naContext c)
.bases<NasalElement>()
.member("_node_ghost", &elementGetNode<canvas::Window>)
.method("_getCanvasDecoration", &canvas::Window::getCanvasDecoration);
}
nasal::Hash globals_module(globals, c),
canvas_module = globals_module.createHash("canvas");

View file

@ -81,6 +81,8 @@ static naRef f_http_load(const nasal::CallContext& ctx)
//------------------------------------------------------------------------------
naRef initNasalHTTP(naRef globals, naContext c)
{
if (!NasalRequest::isInit()) {
using simgear::HTTP::Request;
NasalRequest::init("http.Request")
.member("url", &Request::url)
@ -107,6 +109,8 @@ naRef initNasalHTTP(naRef globals, naContext c)
.bases<NasalRequest>()
.member("response", &MemoryRequest::responseBody);
}
nasal::Hash globals_module(globals, c),
http = globals_module.createHash("http");

View file

@ -1813,6 +1813,7 @@ private:
int _gcSaveKey;
};
class NasalFPDelegateFactory : public FlightPlan::DelegateFactory
{
public:
@ -1823,7 +1824,7 @@ public:
_gcSaveKey = _nasal->gcSave(_func);
}
~NasalFPDelegateFactory()
virtual ~NasalFPDelegateFactory()
{
_nasal->gcRelease(_gcSaveKey);
}
@ -1845,6 +1846,20 @@ private:
int _gcSaveKey;
};
static std::vector<NasalFPDelegateFactory*> static_nasalDelegateFactories;
void shutdownNasalPositioned()
{
std::vector<NasalFPDelegateFactory*>::iterator it;
for (it = static_nasalDelegateFactories.begin();
it != static_nasalDelegateFactories.end(); ++it)
{
FlightPlan::unregisterDelegateFactory(*it);
delete (*it);
}
static_nasalDelegateFactories.clear();
}
static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args)
{
if ((argc < 1) || !naIsFunc(args[0])) {
@ -1853,7 +1868,7 @@ static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args)
NasalFPDelegateFactory* factory = new NasalFPDelegateFactory(args[0]);
FlightPlan::registerDelegateFactory(factory);
static_nasalDelegateFactories.push_back(factory);
return naNil();
}

View file

@ -31,5 +31,6 @@ bool geodFromHash(naRef ref, SGGeod& result);
naRef initNasalPositioned(naRef globals, naContext c);
naRef initNasalPositioned_cppbind(naRef globals, naContext c);
void postinitNasalPositioned(naRef globals, naContext c);
void shutdownNasalPositioned();
#endif // of SCRIPTING_NASAL_POSITIONED_HXX

View file

@ -459,6 +459,8 @@ static naRef f_sortByRange(nasal::CallContext ctx)
//------------------------------------------------------------------------------
naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c)
{
if (!NasalPositioned::isInit()) {
NasalPositioned::init("Positioned")
.member("id", &FGPositioned::ident)
.member("ident", &FGPositioned::ident) // TODO to we really need id and ident?
@ -502,6 +504,7 @@ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c)
.method("getStar", &FGAirport::findSTARWithIdent)
.method("getIAP", &FGAirport::findApproachWithIdent)
.method("tostring", &FGAirport::toString);
}
nasal::Hash globals(globalsRef, c),
positioned( globals.createHash("positioned") );

View file

@ -246,13 +246,6 @@ naRef FGNasalSys::callMethod(naRef code, naRef self, int argc, naRef* args, naRe
FGNasalSys::~FGNasalSys()
{
nasalSys = 0;
map<int, FGNasalListener *>::iterator it, end = _listener.end();
for(it = _listener.begin(); it != end; ++it)
delete it->second;
naFreeContext(_context);
_globals = naNil();
_string = naNil();
}
bool FGNasalSys::parseAndRun(const char* sourceCode)
@ -601,10 +594,12 @@ static naRef f_findDataDir(naContext c, naRef me, int argc, naRef* args)
class NasalCommand : public SGCommandMgr::Command
{
public:
NasalCommand(FGNasalSys* sys, naRef f) :
NasalCommand(FGNasalSys* sys, naRef f, const std::string& name) :
_sys(sys),
_func(f)
_func(f),
_name(name)
{
globals->get_commands()->addCommandObject(_name, this);
_gcRoot = sys->gcSave(f);
}
@ -628,6 +623,7 @@ private:
FGNasalSys* _sys;
naRef _func;
int _gcRoot;
std::string _name;
};
static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args)
@ -635,20 +631,16 @@ static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args)
if(argc != 2 || !naIsString(args[0]) || !naIsFunc(args[1]))
naRuntimeError(c, "bad arguments to addcommand()");
naRef func = args[1];
NasalCommand* cmd = new NasalCommand(nasalSys, func);
globals->get_commands()->addCommandObject(naStr_data(args[0]), cmd);
nasalSys->addCommand(args[1], naStr_data(args[0]));
return naNil();
}
static naRef f_removeCommand(naContext c, naRef me, int argc, naRef* args)
{
SGCommandMgr::Command* cmd = globals->get_commands()->getCommand(naStr_data(args[0]));
// SGCommandMgr::Command* cmd = globals->get_commands()->removeCommand(naStr_data(args[0]))
delete cmd;
if ((argc < 1) || !naIsString(args[0]))
naRuntimeError(c, "bad argument to removecommand()");
globals->get_commands()->removeCommand(naStr_data(args[0]));
return naNil();
}
@ -782,13 +774,15 @@ void FGNasalSys::init()
initNasalCondition(_globals, _context);
initNasalHTTP(_globals, _context);
NasalTimerObj::init("Timer")
.method("start", &TimerObj::start)
.method("stop", &TimerObj::stop)
.method("restart", &TimerObj::restart)
.member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot)
.member("isRunning", &TimerObj::isRunning);
if (!NasalTimerObj::isInit()) {
NasalTimerObj::init("Timer")
.method("start", &TimerObj::start)
.method("stop", &TimerObj::stop)
.method("restart", &TimerObj::restart)
.member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot)
.member("isRunning", &TimerObj::isRunning);
}
// Now load the various source files in the Nasal directory
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
loadScriptDirectory(nasalDir);
@ -816,6 +810,36 @@ void FGNasalSys::init()
postinitNasalGUI(_globals, _context);
}
void FGNasalSys::shutdown()
{
shutdownNasalPositioned();
map<int, FGNasalListener *>::iterator it, end = _listener.end();
for(it = _listener.begin(); it != end; ++it)
delete it->second;
_listener.clear();
NasalCommandDict::iterator j = _commands.begin();
for (; j != _commands.end(); ++j) {
globals->get_commands()->removeCommand(j->first);
}
_commands.clear();
naClearSaved();
_string = naNil(); // will be freed by _context
naFreeContext(_context);
//setWatchedRef(_globals);
// remove the recursive reference in globals
hashset(_globals, "globals", naNil());
_globals = naNil();
naGC();
}
naRef FGNasalSys::wrappedPropsNode(SGPropertyNode* aProps)
{
static naRef wrapNodeFunc = naNil();
@ -1251,6 +1275,30 @@ void FGNasalSys::registerToUnload(FGNasalModelData *data)
_unloadList.push(data);
}
void FGNasalSys::addCommand(naRef func, const std::string& name)
{
if (_commands.find(name) != _commands.end()) {
SG_LOG(SG_NASAL, SG_WARN, "duplicate add of command:" << name);
return;
}
NasalCommand* cmd = new NasalCommand(this, func, name);
_commands[name] = cmd;
}
void FGNasalSys::removeCommand(const std::string& name)
{
NasalCommandDict::iterator it = _commands.find(name);
if (it == _commands.end()) {
SG_LOG(SG_NASAL, SG_WARN, "remove of unknwon command:" << name);
return;
}
// will delete the NasalCommand instance
globals->get_commands()->removeCommand(name);
_commands.erase(it);
}
//////////////////////////////////////////////////////////////////////////
// FGNasalListener class.

View file

@ -21,6 +21,7 @@ class FGNasalScript;
class FGNasalListener;
class SGCondition;
class FGNasalModelData;
class NasalCommand;
namespace simgear { class BufferedLogCallback; }
@ -33,6 +34,8 @@ public:
FGNasalSys();
virtual ~FGNasalSys();
virtual void init();
virtual void shutdown();
virtual void update(double dt);
// Loads a nasal script from an external file and inserts it as a
@ -84,6 +87,9 @@ public:
void deleteModule(const char* moduleName);
void addCommand(naRef func, const std::string& name);
void removeCommand(const std::string& name);
/**
* Set member of specified hash to given value
*/
@ -173,6 +179,9 @@ private:
SGPropertyNode_ptr _cmdArg;
simgear::BufferedLogCallback* _log;
typedef std::map<std::string, NasalCommand*> NasalCommandDict;
NasalCommandDict _commands;
public:
void handleTimer(NasalTimer* t);
};