374 lines
9.9 KiB
C++
374 lines
9.9 KiB
C++
// Filename: interrogate_module.cxx
|
|
// Created by: drose (08Aug00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// This program generates a module-level file for interrogate. This
|
|
// is a higher level than library, and groups several libraries
|
|
// together. Presently, the only thing that goes into the module file
|
|
// is a python table, but who knows what the future holds.
|
|
|
|
#include "interrogate_interface.h"
|
|
#include "interrogate_request.h"
|
|
#include "load_dso.h"
|
|
#include "pystub.h"
|
|
#include "pnotify.h"
|
|
|
|
#include "set"
|
|
|
|
// If our system getopt() doesn't come with getopt_long_only(), then use
|
|
// the GNU flavor that we've got in tool for this purpose.
|
|
#ifndef HAVE_GETOPT_LONG_ONLY
|
|
#include "gnu_getopt.h"
|
|
#else
|
|
#include <getopt.h>
|
|
#endif
|
|
|
|
Filename output_code_filename;
|
|
string module_name;
|
|
string library_name;
|
|
bool build_c_wrappers = false;
|
|
bool build_python_wrappers = false;
|
|
bool build_python_native_wrappers = false;
|
|
bool track_interpreter = false;
|
|
|
|
// Short command-line options.
|
|
static const char *short_options = "";
|
|
|
|
// Long command-line options.
|
|
enum CommandOptions {
|
|
CO_oc = 256,
|
|
CO_module,
|
|
CO_library,
|
|
CO_c,
|
|
CO_python,
|
|
CO_python_native,
|
|
CO_track_interpreter,
|
|
};
|
|
|
|
static struct option long_options[] = {
|
|
{ "oc", required_argument, NULL, CO_oc },
|
|
{ "module", required_argument, NULL, CO_module },
|
|
{ "library", required_argument, NULL, CO_library },
|
|
{ "c", no_argument, NULL, CO_c },
|
|
{ "python", no_argument, NULL, CO_python },
|
|
{ "python-native", no_argument, NULL, CO_python_native },
|
|
{ "track-interpreter", no_argument, NULL, CO_track_interpreter },
|
|
{ NULL }
|
|
};
|
|
|
|
/*
|
|
static string
|
|
upcase_string(const string &str) {
|
|
string result;
|
|
for (string::const_iterator si = str.begin();
|
|
si != str.end();
|
|
++si) {
|
|
result += toupper(*si);
|
|
}
|
|
return result;
|
|
}
|
|
*/
|
|
|
|
int write_python_table_native(ostream &out)
|
|
{
|
|
out << "\n#include \"dtoolbase.h\"\n"
|
|
<< "#include \"interrogate_request.h\"\n\n"
|
|
<< "#undef _POSIX_C_SOURCE\n"
|
|
<< "#include \"py_panda.h\"\n\n";
|
|
|
|
int count = 0;
|
|
|
|
std::set<std::string > Libraries;
|
|
|
|
|
|
// out << "extern \"C\" {\n";
|
|
|
|
// Walk through all of the Python functions.
|
|
int num_functions = interrogate_number_of_functions();
|
|
int fi;
|
|
for (fi = 0; fi < num_functions; fi++)
|
|
{
|
|
FunctionIndex function_index = interrogate_get_function(fi);
|
|
|
|
// Consider only those that belong in the module we asked for.
|
|
if (interrogate_function_has_module_name(function_index) &&
|
|
module_name == interrogate_function_module_name(function_index))
|
|
{
|
|
// if it has a library name add it to set of libraries
|
|
if(interrogate_function_has_library_name(function_index))
|
|
Libraries.insert(interrogate_function_library_name(function_index));
|
|
}
|
|
}
|
|
|
|
for(int ti = 0; ti < interrogate_number_of_types(); ti++)
|
|
{
|
|
TypeIndex thetype = interrogate_get_type(ti);
|
|
if(interrogate_type_has_module_name(thetype) && module_name == interrogate_type_module_name(thetype))
|
|
{
|
|
if(interrogate_type_has_library_name(thetype))
|
|
Libraries.insert(interrogate_type_library_name(thetype));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
std::set<std::string >::iterator ii;
|
|
for(ii = Libraries.begin(); ii != Libraries.end(); ii++)
|
|
{
|
|
printf("Referencing Library %s\n",(*ii).c_str());
|
|
out << "extern LibrayDef "<< *ii << "_moddef ;\n";
|
|
}
|
|
|
|
|
|
|
|
|
|
out << "#ifdef _WIN32\n"
|
|
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
|
|
<< "#else\n"
|
|
<< "extern \"C\" void init" << library_name << "();\n"
|
|
<< "#endif\n\n"
|
|
|
|
<< "void init" << library_name << "() \n{\n";
|
|
if (track_interpreter) {
|
|
out << " in_interpreter = 1;\n";
|
|
}
|
|
|
|
out << " LibrayDef *defs[] = {";
|
|
for(ii = Libraries.begin(); ii != Libraries.end(); ii++)
|
|
out << "&"<< *ii << "_moddef,";
|
|
|
|
out << " NULL };\n ";
|
|
|
|
|
|
out << " Dtool_PyModuleInitHelper( defs, \"" << library_name << "\");\n";
|
|
out << "\n\n\n}\n";
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
|
|
|
|
int write_python_table(ostream &out)
|
|
{
|
|
out << "\n#include \"dtoolbase.h\"\n"
|
|
<< "#include \"interrogate_request.h\"\n\n"
|
|
<< "#undef _POSIX_C_SOURCE\n"
|
|
<< "#include \"Python.h\"\n\n";
|
|
|
|
int count = 0;
|
|
|
|
// First, we have to declare extern C prototypes for each of the
|
|
// function names.
|
|
|
|
out << "extern \"C\" {\n";
|
|
|
|
// Walk through all of the Python functions.
|
|
int num_functions = interrogate_number_of_functions();
|
|
int fi;
|
|
for (fi = 0; fi < num_functions; fi++) {
|
|
FunctionIndex function_index = interrogate_get_function(fi);
|
|
|
|
// Consider only those that belong in the module we asked for.
|
|
if (interrogate_function_has_module_name(function_index) &&
|
|
module_name == interrogate_function_module_name(function_index)) {
|
|
|
|
// For each function, get all of the python wrappers.
|
|
int num_wrappers =
|
|
interrogate_function_number_of_python_wrappers(function_index);
|
|
|
|
for (int wi = 0; wi < num_wrappers; wi++) {
|
|
FunctionWrapperIndex wrapper_index =
|
|
interrogate_function_python_wrapper(function_index, wi);
|
|
|
|
if (interrogate_wrapper_is_callable_by_name(wrapper_index)) {
|
|
count++;
|
|
const char *wrapper_name =
|
|
interrogate_wrapper_name(wrapper_index);
|
|
out << " PyObject *" << wrapper_name
|
|
<< "(PyObject *self, PyObject *args);\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
out << "}\n\n";
|
|
|
|
// Now go back through and build the table of function names.
|
|
out << "static PyMethodDef python_methods[" << count + 1 << "] = {\n";
|
|
|
|
// Walk through all of the Python functions.
|
|
for (fi = 0; fi < num_functions; fi++) {
|
|
FunctionIndex function_index = interrogate_get_function(fi);
|
|
|
|
// Consider only those that belong in the module we asked for.
|
|
if (interrogate_function_has_module_name(function_index) &&
|
|
module_name == interrogate_function_module_name(function_index)) {
|
|
|
|
// For each function, get all of the python wrappers.
|
|
int num_wrappers =
|
|
interrogate_function_number_of_python_wrappers(function_index);
|
|
for (int wi = 0; wi < num_wrappers; wi++) {
|
|
FunctionWrapperIndex wrapper_index =
|
|
interrogate_function_python_wrapper(function_index, wi);
|
|
|
|
if (interrogate_wrapper_is_callable_by_name(wrapper_index)) {
|
|
const char *wrapper_name =
|
|
interrogate_wrapper_name(wrapper_index);
|
|
out << " { \""
|
|
<< wrapper_name << "\", &"
|
|
<< wrapper_name << ", METH_VARARGS },\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (library_name.empty()) {
|
|
library_name = module_name;
|
|
}
|
|
|
|
out << " { NULL, NULL }\n"
|
|
<< "};\n\n"
|
|
|
|
<< "#ifdef _WIN32\n"
|
|
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
|
|
<< "#else\n"
|
|
<< "extern \"C\" void init" << library_name << "();\n"
|
|
<< "#endif\n\n"
|
|
|
|
<< "void init" << library_name << "() {\n";
|
|
if (track_interpreter) {
|
|
out << " in_interpreter = 1;\n";
|
|
}
|
|
out << " Py_InitModule(\"" << library_name << "\", python_methods);\n"
|
|
<< "}\n\n";
|
|
|
|
return count;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
extern char *optarg;
|
|
extern int optind;
|
|
int flag;
|
|
|
|
flag = getopt_long_only(argc, argv, short_options, long_options, NULL);
|
|
while (flag != EOF) {
|
|
switch (flag) {
|
|
case CO_oc:
|
|
output_code_filename = optarg;
|
|
break;
|
|
|
|
case CO_module:
|
|
module_name = optarg;
|
|
break;
|
|
|
|
case CO_library:
|
|
library_name = optarg;
|
|
break;
|
|
|
|
case CO_c:
|
|
build_c_wrappers = true;
|
|
break;
|
|
|
|
case CO_python:
|
|
build_python_wrappers = true;
|
|
break;
|
|
|
|
case CO_python_native:
|
|
build_python_native_wrappers = true;
|
|
break;
|
|
|
|
case CO_track_interpreter:
|
|
track_interpreter = true;
|
|
break;
|
|
|
|
default:
|
|
exit(1);
|
|
}
|
|
flag = getopt_long_only(argc, argv, short_options, long_options, NULL);
|
|
}
|
|
|
|
argc -= (optind-1);
|
|
argv += (optind-1);
|
|
|
|
if (argc < 2) {
|
|
nout
|
|
<< "\nUsage:\n"
|
|
<< " interrogate-module [opts] libname.in [libname.in ...]\n\n";
|
|
exit(1);
|
|
}
|
|
|
|
output_code_filename.set_text();
|
|
|
|
if (!build_c_wrappers && !build_python_wrappers && !build_python_native_wrappers) {
|
|
build_c_wrappers = true;
|
|
}
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
string param = argv[i];
|
|
|
|
|
|
if (param.length() > 3 && param.substr(param.length() - 3) == ".in") {
|
|
// If the filename ends in ".in", it's an interrogate database
|
|
// file, not a shared library--read it directly.
|
|
interrogate_request_database(param.c_str());
|
|
|
|
} else {
|
|
// Otherwise, assume it's a shared library, and try to load it.
|
|
Filename pathname = argv[i];
|
|
pathname.set_type(Filename::T_dso);
|
|
nout << "Loading " << pathname << "\n";
|
|
void *dl = load_dso(pathname);
|
|
if (dl == NULL) {
|
|
nout << "Unable to load: " << load_dso_error() << "\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now output the table.
|
|
if (!output_code_filename.empty())
|
|
{
|
|
ofstream output_code;
|
|
|
|
if (!output_code_filename.open_write(output_code))
|
|
{
|
|
nout << "Unable to write to " << output_code_filename << "\n";
|
|
} else {
|
|
|
|
if (build_python_wrappers) {
|
|
int count = write_python_table(output_code);
|
|
nout << count << " python function wrappers exported.\n";
|
|
}
|
|
|
|
if (build_python_native_wrappers) {
|
|
write_python_table_native(output_code);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (interrogate_error_flag()) {
|
|
nout << "Error reading interrogate data.\n";
|
|
output_code_filename.unlink();
|
|
exit(1);
|
|
}
|
|
|
|
return (0);
|
|
}
|