254 lines
6.6 KiB
C++
254 lines
6.6 KiB
C++
/**
|
|
* PANDA 3D SOFTWARE
|
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
*
|
|
* All use of this software is subject to the terms of the revised BSD
|
|
* license. You should have received a copy of this license along
|
|
* with this source code in a file named "LICENSE."
|
|
*
|
|
* @file interfaceMakerC.cxx
|
|
* @author drose
|
|
* @date 2001-09-25
|
|
*/
|
|
|
|
#include "interfaceMakerC.h"
|
|
#include "interrogateBuilder.h"
|
|
#include "interrogate.h"
|
|
#include "functionRemap.h"
|
|
#include "parameterRemapHandleToInt.h"
|
|
#include "parameterRemapUnchanged.h"
|
|
#include "typeManager.h"
|
|
|
|
#include "interrogateDatabase.h"
|
|
#include "interrogateType.h"
|
|
#include "interrogateFunction.h"
|
|
#include "cppFunctionType.h"
|
|
|
|
using std::ostream;
|
|
|
|
/**
|
|
*
|
|
*/
|
|
InterfaceMakerC::
|
|
InterfaceMakerC(InterrogateModuleDef *def) :
|
|
InterfaceMaker(def)
|
|
{
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
InterfaceMakerC::
|
|
~InterfaceMakerC() {
|
|
}
|
|
|
|
/**
|
|
* Generates the list of function prototypes corresponding to the functions
|
|
* that will be output in write_functions().
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_prototypes(ostream &out,ostream *out_h) {
|
|
// The 'used' attribute prevents emscripten from optimizing it out.
|
|
out <<
|
|
"#if __GNUC__ >= 4\n"
|
|
"#define EXPORT_FUNC extern \"C\" __attribute__((used, visibility(\"default\")))\n"
|
|
"#else\n"
|
|
"#define EXPORT_FUNC extern \"C\"\n"
|
|
"#endif\n\n";
|
|
|
|
FunctionsByIndex::iterator fi;
|
|
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
|
|
Function *func = (*fi).second;
|
|
write_prototype_for(out, func);
|
|
}
|
|
|
|
out << "\n";
|
|
InterfaceMaker::write_prototypes(out,out_h);
|
|
}
|
|
|
|
/**
|
|
* Generates the list of functions that are appropriate for this interface.
|
|
* This function is called *before* write_prototypes(), above.
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_functions(ostream &out) {
|
|
FunctionsByIndex::iterator fi;
|
|
for (fi = _functions.begin(); fi != _functions.end(); ++fi) {
|
|
Function *func = (*fi).second;
|
|
write_function_for(out, func);
|
|
}
|
|
|
|
InterfaceMaker::write_functions(out);
|
|
}
|
|
|
|
/**
|
|
* Allocates a new ParameterRemap object suitable to the indicated parameter
|
|
* type. If struct_type is non-NULL, it is the type of the enclosing class
|
|
* for the function (method) in question.
|
|
*
|
|
* The return value is a newly-allocated ParameterRemap object, if the
|
|
* parameter type is acceptable, or NULL if the parameter type cannot be
|
|
* handled.
|
|
*/
|
|
ParameterRemap *InterfaceMakerC::
|
|
remap_parameter(CPPType *struct_type, CPPType *param_type) {
|
|
// Wrap TypeHandle and ButtonHandle, which are practically just ints, as an
|
|
// integer instead of a pointer. It makes things easier on the scripting
|
|
// language, especially if there has to be a dynamic downcasting system on
|
|
// the scripting language side.
|
|
if (TypeManager::is_handle(param_type)) {
|
|
return new ParameterRemapHandleToInt(param_type);
|
|
|
|
} else {
|
|
return InterfaceMaker::remap_parameter(struct_type, param_type);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method should be overridden and redefined to return true for
|
|
* interfaces that require the implicit "this" parameter, if present, to be
|
|
* passed as the first parameter to any wrapper functions.
|
|
*/
|
|
bool InterfaceMakerC::
|
|
synthesize_this_parameter() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix string used to generate wrapper function names.
|
|
*/
|
|
std::string InterfaceMakerC::
|
|
get_wrapper_prefix() {
|
|
return "_inC";
|
|
}
|
|
|
|
/**
|
|
* Returns the prefix string used to generate unique symbolic names, which are
|
|
* not necessarily C-callable function names.
|
|
*/
|
|
std::string InterfaceMakerC::
|
|
get_unique_prefix() {
|
|
return "c";
|
|
}
|
|
|
|
/**
|
|
* Associates the function wrapper with its function in the appropriate
|
|
* structures in the database.
|
|
*/
|
|
void InterfaceMakerC::
|
|
record_function_wrapper(InterrogateFunction &ifunc,
|
|
FunctionWrapperIndex wrapper_index) {
|
|
ifunc._c_wrappers.push_back(wrapper_index);
|
|
}
|
|
|
|
/**
|
|
* Writes the prototype for the indicated function.
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
|
|
Function::Remaps::const_iterator ri;
|
|
|
|
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
FunctionRemap *remap = (*ri);
|
|
|
|
if (remap->_extension || (remap->_flags & FunctionRemap::F_explicit_self)) {
|
|
continue;
|
|
}
|
|
|
|
if (output_function_names) {
|
|
out << "EXPORT_FUNC ";
|
|
}
|
|
write_function_header(out, func, remap, false);
|
|
out << ";\n";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes the definition for a function that will call the indicated C++
|
|
* function or method.
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_function_for(ostream &out, InterfaceMaker::Function *func) {
|
|
Function::Remaps::const_iterator ri;
|
|
|
|
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
|
|
FunctionRemap *remap = (*ri);
|
|
write_function_instance(out, func, remap);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes out the particular function that handles a single instance of an
|
|
* overloaded function.
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_function_instance(ostream &out, InterfaceMaker::Function *func,
|
|
FunctionRemap *remap) {
|
|
if (remap->_extension || (remap->_flags & FunctionRemap::F_explicit_self)) {
|
|
return;
|
|
}
|
|
|
|
out << "/*\n"
|
|
<< " * C wrapper for\n"
|
|
<< " * ";
|
|
remap->write_orig_prototype(out, 0, false, remap->_num_default_parameters);
|
|
out << "\n"
|
|
<< " */\n";
|
|
|
|
if (!output_function_names) {
|
|
// If we're not saving the function names, don't export it from the
|
|
// library.
|
|
out << "static ";
|
|
}
|
|
|
|
write_function_header(out, func, remap, true);
|
|
out << " {\n";
|
|
|
|
if (generate_spam) {
|
|
write_spam_message(out, remap);
|
|
}
|
|
|
|
std::string return_expr =
|
|
remap->call_function(out, 2, true, "param0");
|
|
return_expr = manage_return_value(out, 2, remap, return_expr);
|
|
if (!return_expr.empty()) {
|
|
out << " return " << return_expr << ";\n";
|
|
}
|
|
|
|
out << "}\n\n";
|
|
}
|
|
|
|
/**
|
|
* Writes the first line of a function definition, either for a prototype or a
|
|
* function body.
|
|
*/
|
|
void InterfaceMakerC::
|
|
write_function_header(ostream &out, InterfaceMaker::Function *func,
|
|
FunctionRemap *remap, bool newline) {
|
|
if (remap->_void_return) {
|
|
out << "void";
|
|
} else {
|
|
out << remap->_return_type->get_new_type()->get_local_name(&parser);
|
|
}
|
|
if (newline) {
|
|
out << "\n";
|
|
} else {
|
|
out << " ";
|
|
}
|
|
|
|
out << remap->_wrapper_name << "(";
|
|
int pn = 0;
|
|
if (pn < (int)remap->_parameters.size()) {
|
|
remap->_parameters[pn]._remap->get_new_type()->
|
|
output_instance(out, remap->get_parameter_name(pn), &parser);
|
|
pn++;
|
|
while (pn < (int)remap->_parameters.size()) {
|
|
out << ", ";
|
|
remap->_parameters[pn]._remap->get_new_type()->
|
|
output_instance(out, remap->get_parameter_name(pn), &parser);
|
|
pn++;
|
|
}
|
|
}
|
|
out << ")";
|
|
}
|