-
Notifications
You must be signed in to change notification settings - Fork 39
/
python_command_creator.cc
85 lines (72 loc) · 2.73 KB
/
python_command_creator.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// This file is part of SWGANH which is released under the MIT license.
// See file LICENSE or go to http://swganh.com/LICENSE
#include "python_command_creator.h"
#include <boost/python.hpp>
#include "swganh/app/swganh_kernel.h"
#include "swganh_core/command/command_interface.h"
#include "swganh_core/command/command_properties.h"
#include "swganh_core/messages/controllers/command_queue_enqueue.h"
#include "swganh/observer/observer_interface.h"
#include "swganh/scripting/utilities.h"
namespace bp = boost::python;
using swganh::app::SwganhKernel;
using swganh::command::CommandInterface;
using swganh::command::CommandProperties;
using swganh::command::PythonCommandCreator;
using swganh::messages::controllers::CommandQueueEnqueue;
using swganh::object::ObjectController;
using swganh::scripting::ScopedGilLock;
PythonCommandCreator::PythonCommandCreator(std::string module_name, std::string class_name)
: module_name_(module_name)
, class_name_(class_name)
{
ScopedGilLock lock;
try
{
command_module_ = bp::import(module_name_.c_str());
}
catch (bp::error_already_set&)
{
swganh::scripting::logPythonException();
}
}
std::shared_ptr<CommandInterface> PythonCommandCreator::operator() (
swganh::app::SwganhKernel* kernel,
const CommandProperties& properties)
{
std::shared_ptr<CommandInterface> command = nullptr;
ScopedGilLock lock;
try
{
#ifdef _DEBUG
//If our first attempt to load the module crashed, we want to import instead of reload!
if(!command_module_.is_none())
{
command_module_ = bp::object(bp::handle<>(PyImport_ReloadModule(command_module_.ptr())));
}
else
{
command_module_ = bp::import(module_name_.c_str());
}
#endif
// Create an instance of the python class and store it in a shared pointer
// so it's deletion can be properly wrapped in a GIL lock
std::shared_ptr<bp::object> new_instance = std::shared_ptr<bp::object>(
new bp::object(command_module_.attr(class_name_.c_str())(bp::ptr(kernel), boost::ref(properties))),
[] (bp::object* obj) { ScopedGilLock lock; delete obj; });
if (!new_instance->is_none())
{
// Extract the C++ base pointer from the python object and store both in a shared pointer
// to ensure there are no lifetime issues (if the bp::object goes out of scope the interface
// pointer is invalidated)
CommandInterface* obj_pointer = bp::extract<CommandInterface*>(*new_instance);
command.reset(obj_pointer, [new_instance] (CommandInterface*) {});
command->SetCommandProperties(properties);
}
}
catch (bp::error_already_set&)
{
swganh::scripting::logPythonException();
}
return command;
}