00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "interfaceMakerPythonObj.h"
00020 #include "interrogateBuilder.h"
00021 #include "interrogate.h"
00022 #include "functionRemap.h"
00023 #include "parameterRemapUnchanged.h"
00024 #include "typeManager.h"
00025 #include "functionWriterPtrFromPython.h"
00026 #include "functionWriterPtrToPython.h"
00027
00028 #include "interrogateDatabase.h"
00029 #include "interrogateType.h"
00030 #include "interrogateFunction.h"
00031 #include "cppFunctionType.h"
00032
00033
00034
00035
00036
00037
00038 InterfaceMakerPythonObj::
00039 InterfaceMakerPythonObj(InterrogateModuleDef *def) :
00040 InterfaceMakerPython(def)
00041 {
00042 }
00043
00044
00045
00046
00047
00048
00049 InterfaceMakerPythonObj::
00050 ~InterfaceMakerPythonObj() {
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 void InterfaceMakerPythonObj::
00061 write_prototypes(ostream &out) {
00062 Functions::iterator fi;
00063 for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00064 Function *func = (*fi);
00065 write_prototype_for(out, func);
00066 }
00067
00068 out << "\n";
00069 InterfaceMakerPython::write_prototypes(out);
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079 void InterfaceMakerPythonObj::
00080 write_functions(ostream &out) {
00081 Functions::iterator fi;
00082 for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
00083 Function *func = (*fi);
00084 write_function_for(out, func);
00085 }
00086
00087 InterfaceMakerPython::write_functions(out);
00088
00089
00090 Objects::iterator oi;
00091 for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
00092 Object *object = (*oi).second;
00093
00094 write_class_wrapper(out, object);
00095 }
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 void InterfaceMakerPythonObj::
00105 write_module(ostream &out, InterrogateModuleDef *def) {
00106 InterfaceMakerPython::write_module(out, def);
00107
00108 out << "static PyMethodDef python_obj_funcs[] = {\n";
00109
00110 Objects::iterator oi;
00111 for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
00112 Object *object = (*oi).second;
00113
00114 Functions::iterator fi;
00115 for (fi = object->_constructors.begin();
00116 fi != object->_constructors.end();
00117 ++fi) {
00118 Function *func = (*fi);
00119 out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
00120 << ", METH_VARARGS },\n";
00121 }
00122 }
00123 out << " { NULL, NULL }\n"
00124 << "};\n\n"
00125
00126 << "#ifdef _WIN32\n"
00127 << "extern \"C\" __declspec(dllexport) void init" << def->library_name << "();\n"
00128 << "#else\n"
00129 << "extern \"C\" void init" << def->library_name << "();\n"
00130 << "#endif\n\n"
00131
00132 << "void init" << def->library_name << "() {\n"
00133 << " Py_InitModule(\"" << def->library_name
00134 << "\", python_obj_funcs);\n"
00135 << "}\n\n";
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 bool InterfaceMakerPythonObj::
00147 synthesize_this_parameter() {
00148 return true;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158 string InterfaceMakerPythonObj::
00159 get_builder_name(CPPType *struct_type) {
00160 return "get_python_class_" +
00161 InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser));
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 string InterfaceMakerPythonObj::
00171 get_wrapper_prefix() {
00172 return "wpo_";
00173 }
00174
00175
00176
00177
00178
00179
00180 void InterfaceMakerPythonObj::
00181 write_class_wrapper(ostream &out, InterfaceMaker::Object *object) {
00182 CPPType *struct_type = object->_itype._cpptype;
00183 if (struct_type == (CPPType *)NULL) {
00184 return;
00185 }
00186
00187 string name = get_builder_name(struct_type);
00188 string python_name =
00189 InterrogateBuilder::clean_identifier(struct_type->get_simple_name());
00190
00191 out << "/*\n"
00192 << " * Generate unique Python class for "
00193 << struct_type->get_local_name(&parser) << "\n"
00194 << " */\n"
00195 << "PyObject *\n"
00196 << name << "() {\n"
00197 << " static PyObject *wrapper = (PyObject *)NULL;\n"
00198 << " static PyMethodDef methods[] = {\n";
00199
00200 int methods_size = 0;
00201 int class_methods_size = 0;
00202
00203 Functions::iterator fi;
00204 for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
00205 Function *func = (*fi);
00206 if (func->_has_this) {
00207 out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
00208 << ", METH_VARARGS },\n";
00209 methods_size++;
00210 }
00211 }
00212
00213 out << " };\n"
00214 << " static const int methods_size = " << methods_size << ";\n\n"
00215 << " static PyMethodDef class_methods[] = {\n";
00216
00217 for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) {
00218 Function *func = (*fi);
00219 if (!func->_has_this) {
00220 out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
00221 << ", METH_VARARGS },\n";
00222 class_methods_size++;
00223 }
00224 }
00225
00226 out << " };\n"
00227 << " static const int class_methods_size = " << class_methods_size << ";\n\n"
00228 << " if (wrapper == (PyObject *)NULL) {\n"
00229 << " int i;\n"
00230 << " PyObject *bases = PyTuple_New(0);\n"
00231 << " PyObject *dict = PyDict_New();\n"
00232 << " PyObject *name = PyString_FromString(\""
00233 << python_name << "\");\n"
00234 << " wrapper = PyClass_New(bases, dict, name);\n"
00235 << " for (i = 0; i < methods_size; i++) {\n"
00236 << " PyObject *function, *method;\n"
00237 << " function = PyCFunction_New(&methods[i], (PyObject *)NULL);\n"
00238 << " method = PyMethod_New(function, (PyObject *)NULL, wrapper);\n"
00239 << " PyDict_SetItemString(dict, methods[i].ml_name, method);\n"
00240 << " }\n"
00241 << " for (i = 0; i < class_methods_size; i++) {\n"
00242 << " PyObject *function;\n"
00243 << " function = PyCFunction_New(&class_methods[i], (PyObject *)NULL);\n"
00244 << " PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n"
00245 << " }\n"
00246 << " }\n"
00247 << " return wrapper;\n"
00248 << "}\n\n";
00249 }
00250
00251
00252
00253
00254
00255
00256 void InterfaceMakerPythonObj::
00257 write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
00258 out << "static PyObject *"
00259 << func->_name << "(PyObject *self, PyObject *args);\n";
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 void InterfaceMakerPythonObj::
00269 write_function_for(ostream &out, InterfaceMaker::Function *func) {
00270 Function::Remaps::const_iterator ri;
00271 out << "/*\n"
00272 << " * Python object wrapper for\n";
00273 for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00274 FunctionRemap *remap = (*ri);
00275 out << " * ";
00276 remap->write_orig_prototype(out, 0);
00277 out << "\n";
00278 }
00279 out << " */\n";
00280
00281 out << "static PyObject *"
00282 << func->_name << "(PyObject *, PyObject *args) {\n";
00283
00284
00285 string expected_params = "Arguments must match one of:";
00286
00287 for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
00288 FunctionRemap *remap = (*ri);
00289 expected_params += "\\n ";
00290 write_function_instance(out, 2, func, remap, expected_params);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300 out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n"
00301 << " return (PyObject *)NULL;\n";
00302
00303 out << "}\n\n";
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 void InterfaceMakerPythonObj::
00313 write_function_instance(ostream &out, int indent_level,
00314 InterfaceMaker::Function *func,
00315 FunctionRemap *remap, string &expected_params) {
00316 indent(out, indent_level) << "{\n";
00317 indent(out, indent_level + 2) << "/* ";
00318 remap->write_orig_prototype(out, 0);
00319 out << " */\n\n";
00320
00321 string format_specifiers;
00322 string parameter_list;
00323 vector_string pexprs;
00324
00325
00326
00327
00328
00329
00330 expected_params += remap->_cppfunc->get_simple_name();
00331 expected_params += "(";
00332
00333 int pn;
00334 for (pn = 0; pn < (int)remap->_parameters.size(); pn++) {
00335 if (pn != 0) {
00336 expected_params += ", ";
00337 }
00338
00339 indent(out, indent_level + 2);
00340 CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
00341 CPPType *type = remap->_parameters[pn]._remap->get_new_type();
00342 string param_name = remap->get_parameter_name(pn);
00343
00344
00345
00346 string pexpr_string =
00347 "(" + type->get_local_name(&parser) + ")" + param_name;
00348
00349 if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) {
00350 if (TypeManager::is_char_pointer(orig_type)) {
00351 out << "char *" << param_name;
00352 format_specifiers += "s";
00353 parameter_list += ", &" + param_name;
00354
00355 } else {
00356 out << "char *" << param_name
00357 << "_str; int " << param_name << "_len";
00358 format_specifiers += "s#";
00359 parameter_list += ", &" + param_name
00360 + "_str, &" + param_name + "_len";
00361 pexpr_string = "basic_string<char>(" +
00362 param_name + "_str, " +
00363 param_name + "_len)";
00364 }
00365 expected_params += "string";
00366
00367 } else if (TypeManager::is_bool(type)) {
00368 out << "PyObject *" << param_name;
00369 format_specifiers += "O";
00370 parameter_list += ", &" + param_name;
00371 pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)";
00372 expected_params += "bool";
00373
00374 } else if (TypeManager::is_integer(type)) {
00375 out << "int " << param_name;
00376 format_specifiers += "i";
00377 parameter_list += ", &" + param_name;
00378 expected_params += "integer";
00379
00380 } else if (TypeManager::is_float(type)) {
00381 out << "double " << param_name;
00382 format_specifiers += "d";
00383 parameter_list += ", &" + param_name;
00384 expected_params += "float";
00385
00386 } else if (TypeManager::is_char_pointer(type)) {
00387 out << "char *" << param_name;
00388 format_specifiers += "s";
00389 parameter_list += ", &" + param_name;
00390 expected_params += "string";
00391
00392 } else if (TypeManager::is_pointer(type)) {
00393 FunctionWriterPtrFromPython *writer = get_ptr_from_python(type);
00394 writer->get_pointer_type()->output_instance(out, param_name, &parser);
00395 format_specifiers += "O&";
00396 parameter_list += ", &" + writer->get_name() + ", &" + param_name;
00397 expected_params += writer->get_type()->get_preferred_name();
00398
00399 } else {
00400
00401 out << "PyObject *" << param_name;
00402 format_specifiers += "O";
00403 parameter_list += ", &" + param_name;
00404 expected_params += "any";
00405 }
00406
00407 if (remap->_parameters[pn]._has_name) {
00408 expected_params += " " + remap->_parameters[pn]._name;
00409 }
00410
00411 out << ";\n";
00412 pexprs.push_back(pexpr_string);
00413 }
00414 expected_params += ")";
00415
00416 indent(out, indent_level + 2)
00417 << "if (PyArg_ParseTuple(args, \"" << format_specifiers
00418 << "\"" << parameter_list << ")) {\n";
00419
00420 if (track_interpreter) {
00421 indent(out, indent_level + 4)
00422 << "in_interpreter = 0;\n";
00423 }
00424
00425 if (!remap->_void_return &&
00426 remap->_return_type->new_type_is_atomic_string()) {
00427
00428
00429 string return_expr =
00430 remap->call_function(out, indent_level + 4, false, "param0", pexprs);
00431
00432 CPPType *type = remap->_return_type->get_orig_type();
00433 indent(out, indent_level + 4);
00434 type->output_instance(out, "return_value", &parser);
00435 out << " = " << return_expr << ";\n";
00436
00437 if (track_interpreter) {
00438 indent(out, indent_level + 4)
00439 << "in_interpreter = 1;\n";
00440 }
00441
00442 return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
00443 test_assert(out, indent_level + 4);
00444 pack_return_value(out, indent_level + 4, remap, return_expr);
00445
00446 } else {
00447 string return_expr =
00448 remap->call_function(out, indent_level + 4, true, "param0", pexprs);
00449 if (return_expr.empty()) {
00450 if (track_interpreter) {
00451 indent(out, indent_level + 4)
00452 << "in_interpreter = 1;\n";
00453 }
00454 test_assert(out, indent_level + 4);
00455 indent(out, indent_level + 4)
00456 << "return Py_BuildValue(\"\");\n";
00457
00458 } else {
00459 CPPType *type = remap->_return_type->get_temporary_type();
00460 indent(out, indent_level + 4);
00461 type->output_instance(out, "return_value", &parser);
00462 out << " = " << return_expr << ";\n";
00463 if (track_interpreter) {
00464 indent(out, indent_level + 4)
00465 << "in_interpreter = 1;\n";
00466 }
00467
00468 return_expr = manage_return_value(out, indent_level + 4, remap, "return_value");
00469 test_assert(out, indent_level + 4);
00470 pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr));
00471 }
00472 }
00473
00474 indent(out, indent_level + 2) << "}\n";
00475 indent(out, indent_level + 2)
00476 << "PyErr_Clear();\n";
00477 indent(out, indent_level)
00478 << "}\n";
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 void InterfaceMakerPythonObj::
00488 pack_return_value(ostream &out, int indent_level,
00489 FunctionRemap *remap, string return_expr) {
00490 CPPType *orig_type = remap->_return_type->get_orig_type();
00491 CPPType *type = remap->_return_type->get_new_type();
00492
00493 if (remap->_return_type->new_type_is_atomic_string()) {
00494 if (TypeManager::is_char_pointer(orig_type)) {
00495 indent(out, indent_level)
00496 << "return PyString_FromString(" << return_expr << ");\n";
00497
00498 } else {
00499 indent(out, indent_level)
00500 << "return PyString_FromStringAndSize("
00501 << return_expr << ".data(), " << return_expr << ".length());\n";
00502 }
00503
00504 } else if (TypeManager::is_integer(type)) {
00505 indent(out, indent_level)
00506 << "return PyInt_FromLong(" << return_expr << ");\n";
00507
00508 } else if (TypeManager::is_float(type)) {
00509 indent(out, indent_level)
00510 << "return PyFloat_FromDouble(" << return_expr << ");\n";
00511
00512 } else if (TypeManager::is_char_pointer(type)) {
00513 indent(out, indent_level)
00514 << "return PyString_FromString(" << return_expr << ");\n";
00515
00516 } else if (TypeManager::is_pointer(type)) {
00517 bool caller_manages = remap->_return_value_needs_management;
00518
00519 FunctionWriterPtrToPython *writer = get_ptr_to_python(type);
00520 indent(out, indent_level)
00521 << "return " << writer->get_name() << "(("
00522 << writer->get_pointer_type()->get_local_name(&parser) << ")"
00523 << return_expr << ", " << caller_manages << ");\n";
00524
00525 } else {
00526
00527 indent(out, indent_level)
00528 << "return Py_BuildValue(\"\");\n";
00529 }
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539 FunctionWriterPtrFromPython *InterfaceMakerPythonObj::
00540 get_ptr_from_python(CPPType *type) {
00541 PtrConverter::iterator ci;
00542 ci = _from_python.find(type);
00543 if (ci != _from_python.end()) {
00544
00545 return (FunctionWriterPtrFromPython *)(*ci).second;
00546 }
00547
00548 FunctionWriter *writer =
00549 _function_writers.add_writer(new FunctionWriterPtrFromPython(type));
00550 _from_python.insert(PtrConverter::value_type(type, writer));
00551 return (FunctionWriterPtrFromPython *)writer;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561 FunctionWriterPtrToPython *InterfaceMakerPythonObj::
00562 get_ptr_to_python(CPPType *type) {
00563 PtrConverter::iterator ci;
00564 ci = _to_python.find(type);
00565 if (ci != _to_python.end()) {
00566
00567 return (FunctionWriterPtrToPython *)(*ci).second;
00568 }
00569
00570 FunctionWriter *writer =
00571 _function_writers.add_writer(new FunctionWriterPtrToPython(type));
00572 _to_python.insert(PtrConverter::value_type(type, writer));
00573 return (FunctionWriterPtrToPython *)writer;
00574 }