Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/interrogate/interrogate_module.cxx

Go to the documentation of this file.
00001 // Filename: interrogate_module.cxx
00002 // Created by:  drose (08Aug00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 // This program generates a module-level file for interrogate.  This
00020 // is a higher level than library, and groups several libraries
00021 // together.  Presently, the only thing that goes into the module file
00022 // is a python table, but who knows what the future holds.
00023 
00024 #include <interrogate_interface.h>
00025 #include <interrogate_request.h>
00026 #include <load_dso.h>
00027 #include <pystub.h>
00028 #include <notify.h>
00029 
00030 // If our system getopt() doesn't come with getopt_long_only(), then use
00031 // the GNU flavor that we've got in tool for this purpose.
00032 #ifndef HAVE_GETOPT_LONG_ONLY
00033 #include <gnu_getopt.h>
00034 #else
00035 #include <getopt.h>
00036 #endif
00037 
00038 Filename output_code_filename;
00039 string module_name;
00040 string library_name;
00041 bool build_c_wrappers = false;
00042 bool build_python_wrappers = false;
00043 bool track_interpreter = false;
00044 
00045 // Short command-line options.
00046 static const char *short_options = "";
00047 
00048 // Long command-line options.
00049 enum CommandOptions {
00050   CO_oc = 256,
00051   CO_module,
00052   CO_library,
00053   CO_c,
00054   CO_python,
00055   CO_track_interpreter,
00056 };
00057 
00058 static struct option long_options[] = {
00059   { "oc", required_argument, NULL, CO_oc },
00060   { "module", required_argument, NULL, CO_module },
00061   { "library", required_argument, NULL, CO_library },
00062   { "c", no_argument, NULL, CO_c },
00063   { "python", no_argument, NULL, CO_python },
00064   { "track-interpreter", no_argument, NULL, CO_track_interpreter },
00065   { NULL }
00066 };
00067 
00068 /*
00069 static string
00070 upcase_string(const string &str) {
00071   string result;
00072   for (string::const_iterator si = str.begin();
00073        si != str.end();
00074        ++si) {
00075     result += toupper(*si);
00076   }
00077   return result;
00078 }
00079 */
00080 
00081 int
00082 write_python_table(ostream &out) {
00083   out << "\n#include <dtoolbase.h>\n"
00084       << "#include <interrogate_request.h>\n\n"
00085       << "#include <Python.h>\n\n";
00086 
00087   int count = 0;
00088 
00089   // First, we have to declare extern C prototypes for each of the
00090   // function names.
00091 
00092   out << "extern \"C\" {\n";
00093 
00094   // Walk through all of the Python functions.
00095   int num_functions = interrogate_number_of_functions();
00096   int fi;
00097   for (fi = 0; fi < num_functions; fi++) {
00098     FunctionIndex function_index = interrogate_get_function(fi);
00099 
00100     // Consider only those that belong in the module we asked for.
00101     if (interrogate_function_has_module_name(function_index) &&
00102         module_name == interrogate_function_module_name(function_index)) {
00103 
00104       // For each function, get all of the python wrappers.
00105       int num_wrappers =
00106         interrogate_function_number_of_python_wrappers(function_index);
00107 
00108       for (int wi = 0; wi < num_wrappers; wi++) {
00109         FunctionWrapperIndex wrapper_index =
00110           interrogate_function_python_wrapper(function_index, wi);
00111 
00112         if (interrogate_wrapper_is_callable_by_name(wrapper_index)) {
00113           count++;
00114           const char *wrapper_name =
00115             interrogate_wrapper_name(wrapper_index);
00116           out << "  PyObject *" << wrapper_name
00117               << "(PyObject *self, PyObject *args);\n";
00118         }
00119       }
00120     }
00121   }
00122 
00123   out << "}\n\n";
00124 
00125   // Now go back through and build the table of function names.
00126   out << "static PyMethodDef python_methods[" << count + 1 << "] = {\n";
00127 
00128   // Walk through all of the Python functions.
00129   for (fi = 0; fi < num_functions; fi++) {
00130     FunctionIndex function_index = interrogate_get_function(fi);
00131 
00132     // Consider only those that belong in the module we asked for.
00133     if (interrogate_function_has_module_name(function_index) &&
00134         module_name == interrogate_function_module_name(function_index)) {
00135 
00136       // For each function, get all of the python wrappers.
00137       int num_wrappers =
00138         interrogate_function_number_of_python_wrappers(function_index);
00139       for (int wi = 0; wi < num_wrappers; wi++) {
00140         FunctionWrapperIndex wrapper_index =
00141           interrogate_function_python_wrapper(function_index, wi);
00142 
00143         if (interrogate_wrapper_is_callable_by_name(wrapper_index)) {
00144           const char *wrapper_name =
00145             interrogate_wrapper_name(wrapper_index);
00146           out << "  { \""
00147               << wrapper_name << "\", &"
00148               << wrapper_name << ", METH_VARARGS },\n";
00149         }
00150       }
00151     }
00152   }
00153 
00154   if (library_name.empty()) {
00155     library_name = module_name;
00156   }
00157 
00158   out << "  { NULL, NULL }\n"
00159       << "};\n\n"
00160 
00161       << "#ifdef _WIN32\n"
00162       << "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
00163       << "#else\n"
00164       << "extern \"C\" void init" << library_name << "();\n"
00165       << "#endif\n\n"
00166 
00167       << "void init" << library_name << "() {\n";
00168   if (track_interpreter) {
00169     out << "  in_interpreter = 1;\n";
00170   }
00171   out << "  Py_InitModule(\"" << library_name << "\", python_methods);\n"
00172       << "}\n\n";
00173 
00174   return count;
00175 }
00176 
00177 int
00178 main(int argc, char *argv[]) {
00179   extern char *optarg;
00180   extern int optind;
00181   int flag;
00182 
00183   flag = getopt_long_only(argc, argv, short_options, long_options, NULL);
00184   while (flag != EOF) {
00185     switch (flag) {
00186     case CO_oc:
00187       output_code_filename = optarg;
00188       break;
00189 
00190     case CO_module:
00191       module_name = optarg;
00192       break;
00193 
00194     case CO_library:
00195       library_name = optarg;
00196       break;
00197 
00198     case CO_c:
00199       build_c_wrappers = true;
00200       break;
00201 
00202     case CO_python:
00203       build_python_wrappers = true;
00204       break;
00205 
00206     case CO_track_interpreter:
00207       track_interpreter = true;
00208       break;
00209 
00210     default:
00211       exit(1);
00212     }
00213     flag = getopt_long_only(argc, argv, short_options, long_options, NULL);
00214   }
00215 
00216   argc -= (optind-1);
00217   argv += (optind-1);
00218 
00219   if (argc < 2) {
00220     nout
00221       << "\nUsage:\n"
00222       << "  interrogate-module [opts] libname.in [libname.in ...]\n\n";
00223     exit(1);
00224   }
00225 
00226   output_code_filename.set_text();
00227 
00228   if (!build_c_wrappers && !build_python_wrappers) {
00229     build_c_wrappers = true;
00230   }
00231 
00232   for (int i = 1; i < argc; i++) {
00233     string param = argv[i];
00234 
00235 
00236     if (param.length() > 3 && param.substr(param.length() - 3) == ".in") {
00237       // If the filename ends in ".in", it's an interrogate database
00238       // file, not a shared library--read it directly.
00239       interrogate_request_database(param.c_str());
00240 
00241     } else {
00242       // Otherwise, assume it's a shared library, and try to load it.
00243       Filename pathname = argv[i];
00244       pathname.set_type(Filename::T_dso);
00245       nout << "Loading " << pathname << "\n";
00246       void *dl = load_dso(pathname);
00247       if (dl == NULL) {
00248         nout << "Unable to load: " << load_dso_error() << "\n";
00249         exit(1);
00250       }
00251     }
00252   }
00253 
00254   // Now output the table.
00255   if (!output_code_filename.empty()) {
00256     ofstream output_code;
00257 
00258     if (!output_code_filename.open_write(output_code)) {
00259       nout << "Unable to write to " << output_code_filename << "\n";
00260     } else {
00261       if (build_python_wrappers) {
00262         int count = write_python_table(output_code);
00263         nout << count << " python function wrappers exported.\n";
00264       }
00265     }
00266   }
00267 
00268   return (0);
00269 }

Generated on Thu May 1 22:13:02 2003 for DTool by doxygen1.3