command-line arguments

This commit is contained in:
David Rose 2009-08-17 16:03:49 +00:00
parent 8f96fa71f5
commit 1dda2cfb99
16 changed files with 135 additions and 46 deletions

View File

@ -82,6 +82,25 @@ set_tokens(const P3D_token tokens[], size_t num_tokens) {
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DFileParams::set_args
// Access: Public
// Description: Specifies the command-line arguments associated with
// the instance.
////////////////////////////////////////////////////////////////////
void P3DFileParams::
set_args(int argc, const char *argv[]) {
_args.clear();
for (int i = 0; i < argc; ++i) {
const char *arg = argv[i];
if (arg == NULL) {
arg = "";
}
_args.push_back(arg);
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DFileParams::lookup_token
// Access: Public
@ -136,10 +155,17 @@ make_xml() {
for (ti = _tokens.begin(); ti != _tokens.end(); ++ti) {
const Token &token = (*ti);
TiXmlElement *xtoken = new TiXmlElement("token");
xtoken->SetAttribute("keyword", token._keyword.c_str());
xtoken->SetAttribute("value", token._value.c_str());
xtoken->SetAttribute("keyword", token._keyword);
xtoken->SetAttribute("value", token._value);
xfparams->LinkEndChild(xtoken);
}
Args::const_iterator ai;
for (ai = _args.begin(); ai != _args.end(); ++ai) {
TiXmlElement *xarg = new TiXmlElement("arg");
xarg->SetAttribute("value", (*ai));
xfparams->LinkEndChild(xarg);
}
return xfparams;
}

View File

@ -32,6 +32,7 @@ public:
void set_p3d_filename(const string &p3d_filename);
void set_tokens(const P3D_token tokens[], size_t num_tokens);
void set_args(int argc, const char *argv[]);
inline const string &get_p3d_filename() const;
string lookup_token(const string &keyword) const;
@ -46,9 +47,11 @@ private:
string _value;
};
typedef vector<Token> Tokens;
typedef vector<string> Args;
string _p3d_filename;
Tokens _tokens;
Args _args;
};
#include "p3dFileParams.I"

View File

@ -51,7 +51,8 @@ typedef P3DSplashWindow SplashWindowType;
////////////////////////////////////////////////////////////////////
P3DInstance::
P3DInstance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens, void *user_data) :
const P3D_token tokens[], size_t num_tokens,
int argc, const char *argv[], void *user_data) :
_func(func)
{
_browser_script_object = NULL;

View File

@ -49,7 +49,8 @@ class P3DToplevelObject;
class P3DInstance : public P3D_instance, public P3DReferenceCount {
public:
P3DInstance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens, void *user_data);
const P3D_token tokens[], size_t num_tokens,
int argc, const char *argv[], void *user_data);
~P3DInstance();
void set_p3d_url(const string &p3d_url);

View File

@ -207,8 +207,9 @@ read_contents_file(const string &contents_filename) {
P3DInstance *P3DInstanceManager::
create_instance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens,
void *user_data) {
P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, user_data);
int argc, const char *argv[], void *user_data) {
P3DInstance *inst = new P3DInstance(func, tokens, num_tokens, argc, argv,
user_data);
inst->ref();
_instances.insert(inst);

View File

@ -55,7 +55,7 @@ public:
P3DInstance *
create_instance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens,
void *user_data);
int argc, const char *argv[], void *user_data);
bool set_p3d_filename(P3DInstance *inst, bool is_local,
const string &p3d_filename);

View File

@ -942,7 +942,6 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
}
PyObject *token_list = PyList_New(0);
TiXmlElement *xtoken = xfparams->FirstChildElement("token");
while (xtoken != NULL) {
string keyword, value;
@ -963,11 +962,28 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
xtoken = xtoken->NextSiblingElement("token");
}
PyObject *arg_list = PyList_New(0);
TiXmlElement *xarg = xfparams->FirstChildElement("arg");
while (xarg != NULL) {
string value;
const char *value_c = xarg->Attribute("value");
if (value_c != NULL) {
value = value_c;
}
PyObject *str = Py_BuildValue("s", value.c_str());
PyList_Append(arg_list, str);
Py_DECREF(str);
xarg = xarg->NextSiblingElement("arg");
}
PyObject *result = PyObject_CallMethod
(_runner, (char *)"setP3DFilename", (char *)"sOi", p3d_filename.c_str(),
token_list, inst->get_instance_id());
(_runner, (char *)"setP3DFilename", (char *)"sOOi", p3d_filename.c_str(),
token_list, arg_list, inst->get_instance_id());
Py_DECREF(token_list);
Py_DECREF(arg_list);
if (result == NULL) {
PyErr_Print();

View File

@ -105,12 +105,13 @@ P3D_finalize() {
P3D_instance *
P3D_new_instance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens,
void *user_data) {
int argc, const char *argv[], void *user_data) {
nout << "new_instance\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens, user_data);
P3DInstance *result = inst_mgr->create_instance(func, tokens, num_tokens,
argc, argv, user_data);
RELEASE_LOCK(_api_lock);
return result;
}

View File

@ -224,6 +224,14 @@ typedef struct {
passed to the application, who is free to decide how to interpret
them; they have no meaning at the system level.
The argc/argv parameters are intended for when the plugin is
invoked from the command line; they should be filled a standard
C-style argc/argv parameter list, corresponding to the command-line
parameters passed to the application. They may be 0 and NULL when
the plugin is invoked from the web. As above, this array and its
string data will be copied into the core API's own internal
storage, and need not persist after this call.
The user_data pointer is any arbitrary pointer value; it will be
copied into the _user_data member of the new P3D_instance object.
This pointer is intended for the host to use to store private data
@ -234,6 +242,7 @@ typedef struct {
typedef P3D_instance *
P3D_new_instance_func(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens,
int argc, const char *argv[],
void *user_data);
/* This function should be called at some point after

View File

@ -957,7 +957,8 @@ create_instance() {
if (!_tokens.empty()) {
tokens = &_tokens[0];
}
_p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(), this);
_p3d_inst = P3D_new_instance(request_ready, tokens, _tokens.size(),
0, NULL, this);
if (_p3d_inst != NULL) {
// Now get the browser's window object, to pass to the plugin.

View File

@ -609,30 +609,35 @@ make_parent_window(P3D_window_handle &parent_window,
// play a particular .p3d file.
////////////////////////////////////////////////////////////////////
P3D_instance *Panda3D::
create_instance(const string &arg, P3D_window_type window_type,
create_instance(const string &p3d, P3D_window_type window_type,
int win_x, int win_y, int win_width, int win_height,
P3D_window_handle parent_window, char **args, int num_args) {
P3D_token tokens[] = {
{ "src", arg.c_str() },
};
int num_tokens = sizeof(tokens) / sizeof(P3D_token);
// If the supplied parameter name is a real file, pass it in on the
// parameter list. Otherwise, assume it's a URL and let the plugin
// download it.
Filename p3d_filename = Filename::from_os_specific(arg);
string os_p3d_filename;
Filename p3d_filename = Filename::from_os_specific(p3d);
string os_p3d_filename = p3d;
bool is_local = false;
if (p3d_filename.exists()) {
p3d_filename.make_absolute();
os_p3d_filename = p3d_filename.to_os_specific();
is_local = true;
}
P3D_instance *inst = P3D_new_instance(NULL, tokens, num_tokens, NULL);
// Build up the argument list, beginning with the p3d_filename.
pvector<const char *> argv;
argv.push_back(os_p3d_filename.c_str());
for (int i = 0; i < num_args; ++i) {
argv.push_back(args[i]);
}
P3D_instance *inst = P3D_new_instance(NULL, NULL, 0,
argv.size(), &argv[0], NULL);
if (inst != NULL) {
P3D_instance_setup_window
(inst, window_type, win_x, win_y, win_width, win_height, parent_window);
P3D_instance_start(inst, true, os_p3d_filename.c_str());
P3D_instance_start(inst, is_local, os_p3d_filename.c_str());
}
return inst;

View File

@ -55,11 +55,11 @@ private:
void make_parent_window(P3D_window_handle &parent_window,
int win_width, int win_height);
P3D_instance *create_instance(const string &arg, P3D_window_type window_type,
int win_x, int win_y, int win_width,
int win_height,
P3D_window_handle parent_window,
char **args, int num_args);
P3D_instance *
create_instance(const string &p3d, P3D_window_type window_type,
int win_x, int win_y, int win_width, int win_height,
P3D_window_handle parent_window,
char **args, int num_args);
void delete_instance(P3D_instance *instance);
void usage();

View File

@ -371,6 +371,9 @@ class Freezer:
self.moduleName = moduleName
self.filename = filename
def __repr__(self):
return 'ModuleDef(%s, %s, %s)' % (repr(self.token), repr(self.moduleName), repr(self.filename))
def __init__(self, previous = None, debugLevel = 0):
# Normally, we are freezing for our own platform. Change this
# if untrue.
@ -646,7 +649,6 @@ class Freezer:
parentName, baseName = newName.rsplit('.', 1)
if parentName in excludeDict:
token = excludeDict[parentName]
if token == self.MTInclude:
includes.append(mdef)
elif token == self.MTAuto or token == self.MTGuess:
@ -772,10 +774,12 @@ class Freezer:
# Previously exported.
pass
else:
if newName in self.mf.modules or \
newName in startupModules or \
if mdef.moduleName in self.mf.modules or \
mdef.moduleName in startupModules or \
mdef.filename:
moduleDefs.append((newName, mdef))
else:
print "Unknown module %s" % (mdef.moduleName)
elif token == self.MTForbid:
if not prev or prev.token != self.MTForbid:
moduleDefs.append((newName, mdef))

View File

@ -194,8 +194,9 @@ class Packager:
message = 'No main_module specified for application %s' % (self.packageName)
raise PackagerError, message
if self.mainModule:
if self.mainModule not in self.freezer.modules:
self.freezer.addModule(self.mainModule)
moduleName, newName = self.mainModule
if newName not in self.freezer.modules:
self.freezer.addModule(moduleName, newName = newName)
# Pick up any unfrozen Python files.
self.freezer.done()
@ -601,7 +602,7 @@ class Packager:
if self.version:
xpackage.SetAttribute('version', self.version)
xpackage.SetAttribute('main_module', self.mainModule)
xpackage.SetAttribute('main_module', self.mainModule[1])
for variable, value in self.configs.items():
if isinstance(value, types.UnicodeType):
@ -1463,15 +1464,19 @@ class Packager:
def parse_main_module(self, words):
"""
main_module moduleName
main_module moduleName [newName]
"""
newName = None
try:
command, moduleName = words
if len(words) == 2:
command, moduleName = words
else:
command, moduleName, newName = words
except ValueError:
raise ArgumentError
self.mainModule(moduleName)
self.mainModule(moduleName, newName = newName)
def parse_freeze_exe(self, words):
"""
@ -1879,11 +1884,13 @@ class Packager:
if not self.currentPackage:
raise OutsideOfPackageError
if self.currentPackage.mainModule and self.currentPackage.mainModule != moduleName:
if self.currentPackage.mainModule and self.currentPackage.mainModule[0] != moduleName:
self.notify.warning("Replacing main_module %s with %s" % (
self.currentPackage.mainModule, moduleName))
self.currentPackage.mainModule[0], moduleName))
self.currentPackage.mainModule = moduleName
if not newName:
newName = moduleName
self.currentPackage.mainModule = (moduleName, newName)
def freeze(self, filename, compileToExe = False):
""" Freezes all of the current Python code into either an
@ -1906,10 +1913,17 @@ class Packager:
raise PackagerError, message
if package.mainModule:
if package.mainModule not in freezer.modules:
freezer.addModule(package.mainModule, newName = '__main__')
moduleName, newName = package.mainModule
if compileToExe:
# If we're producing an exe, the main module must
# be called "__main__".
newName = '__main__'
package.mainModule = (moduleName, newName)
if newName not in freezer.modules:
freezer.addModule(moduleName, newName = newName)
else:
freezer.modules['__main__'] = freezer.modules[package.mainModule]
freezer.modules[newName] = freezer.modules[moduleName]
freezer.done(compileToExe = compileToExe)
if not package.dryRun:

View File

@ -128,6 +128,12 @@ def makePackedApp(args):
packager.endPackage(appBase, p3dApplication = True)
def main(appRunner):
""" This function is called when this module is invoked as
packp3d.p3d. """
makePackedApp(appRunner.argv[1:])
if __name__ == '__main__':
try:
makePackedApp(sys.argv[1:])

View File

@ -223,12 +223,12 @@ class AppRunner(DirectObject):
v = VFSImporter.VFSImporter(MultifileRoot)
loader = v.find_module(moduleName)
if not loader:
message = "No %s.py found in application." % (mainName)
message = "No %s found in application." % (moduleName)
raise StandardError, message
main = loader.load_module(moduleName)
if hasattr(main, 'main') and callable(main.main):
main.main()
main.main(self)
def getPandaScriptObject(self):
""" Called by the browser to query the Panda instance's
@ -251,7 +251,7 @@ class AppRunner(DirectObject):
needsResponse = False)
self.deferredEvals = []
def setP3DFilename(self, p3dFilename, tokens = [],
def setP3DFilename(self, p3dFilename, tokens = [], argv = [],
instanceId = None):
# One day we will have support for multiple instances within a
# Python session. Against that day, we save the instance ID
@ -260,6 +260,7 @@ class AppRunner(DirectObject):
self.tokens = tokens
self.tokenDict = dict(tokens)
self.argv = argv
# Tell the browser that Python is up and running, and ready to
# respond to queries.