# Note: do not import this file directly, it is meant to be used as part of # a Python script (generatePythonCode) that sets up variables that this # module depends on import string import os import glob import FFIEnvironment import FFITypes import FFISpecs import FFIRename import FFIConstants import FFIOverload from direct.showbase.PythonUtil import * FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName) # Note: we do a from lib import * here because we do not want # to be dependent on the name of the interrogate library in this code exec('from ' + FFIConstants.InterrogateModuleName + ' import *') def constructGlobalFile(codeDir, CModuleName): """ Open a file that will hold the global values and functions code """ file = open(os.path.join(codeDir, CModuleName + 'Globals' + '.py'), 'w') return file def constructDowncastFile(codeDir, CModuleName): """ Open a file that will hold the global values and functions code """ file = open(os.path.join(codeDir, CModuleName + 'Downcasts' + '.py'), 'w') return file def constructImportFile(codeDir, CModuleName): """ Open a file that will hold the global values and functions code """ file = open(os.path.join(codeDir, CModuleName + 'Modules' + '.py'), 'w') return file def outputGlobalFileImports(file, methodList, CModuleName): # Print the standard header file.write(FFIConstants.generatedHeader) file.write('# CMODULE [' + CModuleName + ']\n') # Import Python's builtin types file.write('from types import IntType, LongType, FloatType, NoneType, StringType\n') file.write('from direct.ffi import FFIExternalObject\n') # Import the C modules CModuleList = [] for method in methodList: if (not (method.typeDescriptor.moduleName in CModuleList)): CModuleList.append(method.typeDescriptor.moduleName) for CModuleName in CModuleList: if CModuleName: file.write('import ' + CModuleName + '\n') moduleList = [] for method in methodList: returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor() returnTypeName = returnType.foreignTypeName if (not (returnTypeName in moduleList)): if (returnType.__class__ == FFITypes.ClassTypeDescriptor): moduleList.append(returnTypeName) # Look at all the arguments argTypes = method.typeDescriptor.argumentTypes for argType in argTypes: # Get the real return type (not derived) argType = argType.typeDescriptor.recursiveTypeDescriptor() if (not argType.isNested): argTypeName = argType.foreignTypeName # Do not put our own module in the import list # Do not put modules already in the list (like a set) if (not (argTypeName in moduleList)): # If this is a class (not a primitive), put it on the list if (argType.__class__ == FFITypes.ClassTypeDescriptor): moduleList.append(argTypeName) for moduleName in moduleList: if moduleName: file.write('import ' + moduleName + '\n') file.write('import ' + moduleName + '1\n') file.write('\n') def outputImportFileImports(file, typeList, CModuleName): """ This is the file that we will import to get all the panda modules """ # Print the standard header file.write(FFIConstants.generatedHeader) file.write('# CMODULE [' + CModuleName + ']\n') file.write('# Import the interrogate module\n') file.write('import ' + FFIConstants.InterrogateModuleName + '\n') file.write('\n') file.write('# Import the C module\n') file.write('import ' + CModuleName + '\n') # Filter out only the class and enum type descriptors (not const, pointers, etc) classTypeList = [] enumTypeList = [] for type in typeList: if (type.__class__ == FFITypes.ClassTypeDescriptor): if (not type.isNested): classTypeList.append(type) elif (type.__class__ == FFITypes.EnumTypeDescriptor): if (not type.isNested): enumTypeList.append(type) # Sort the types based on inheritance, most generic first classTypeList.sort(FFIOverload.inheritanceLevelSort) moduleList = [] for type in classTypeList: moduleList.append(type.foreignTypeName) file.write('# Import enums into the global name space\n') for type in enumTypeList: file.write('from ' + type.enumName + ' import *\n') file.write('\n') file.write('# Import downcast functions\n') file.write('from ' + CModuleName + 'Downcasts import *\n') file.write('\n') file.write('# Import classes\n') for moduleName in moduleList: if moduleName: file.write('import ' + moduleName + '\n') file.write('\n') file.write('# Import classes2\n') for moduleName in moduleList: if moduleName: file.write('import ' + moduleName + '1\n') file.write('\n') file.write('# Import the global module file into our name space\n') file.write('from ' + CModuleName + 'Globals import *\n') file.write('\n') file.write('# Generate the classes\n') #for moduleName in moduleList: # file.write(moduleName + '.generateClass_' + moduleName + '()\n') file.write('\n') file.write('# Copy the classes into our own namespace\n') for moduleName in moduleList: file.write(moduleName + ' = ' + moduleName + '.' + moduleName + '\n') file.write('\n') file.write('# Put the classes in the wrapper class map\n') file.write('from direct.ffi.FFIExternalObject import registerInTypeMap\n') file.write('\n') for moduleName in moduleList: file.write('registerInTypeMap(' + moduleName + ')\n') file.write('\n') def getTypeName(typeIndex, scoped=0): """ Return a fully specified type name for this type index Return the scoped name if asked for it """ nameComponents = [] name = '' if scoped: typeName = interrogate_type_scoped_name(typeIndex) else: typeName = interrogate_type_name(typeIndex) if typeIndex == 0: FFIConstants.notify.debug('typeIndex 0: ' + typeName) if interrogate_type_is_wrapped(typeIndex): typeName = getTypeName(interrogate_type_wrapped_type(typeIndex)) if interrogate_type_is_const(typeIndex): nameComponents.append('const') if interrogate_type_is_pointer(typeIndex): nameComponents.append('ptr') if interrogate_type_is_signed(typeIndex): # signed is now built into the type name #nameComponents.append('signed') pass if interrogate_type_is_unsigned(typeIndex): # unsigned is now built into the type name #nameComponents.append('unsigned') pass if interrogate_type_is_long(typeIndex): nameComponents.append('long') if interrogate_type_is_longlong(typeIndex): nameComponents.append('longLong') if interrogate_type_is_short(typeIndex): nameComponents.append('short') if (len(nameComponents) > 0): typeName = string.capitalize(typeName[0]) + typeName[1:] nameComponents.append(typeName) for i in range(len(nameComponents)): if (i == 0): name = name + nameComponents[i] else: name = name + string.capitalize(nameComponents[i][0]) + nameComponents[i][1:] FFIConstants.notify.debug('typeIndex: ' + repr(typeIndex) + ' typeName: ' + typeName + ' has name: ' + name) if not name: FFIConstants.notify.warning('typeIndex: ' + repr(typeIndex) + ' typeName: ' + typeName + ' has no name') name = "UnnamedType" return name class FFIInterrogateDatabase: def __init__(self, etcPath = []): for dir in etcPath: interrogate_add_search_directory(dir) self.typeIndexMap = {} self.environment = FFIEnvironment.FFIEnvironment() def isDefinedType(self, typeIndex): return typeIndex in self.typeIndexMap def constructDescriptor(self, typeIndex): if interrogate_type_is_atomic(typeIndex): return self.constructPrimitiveTypeDescriptor(typeIndex) elif interrogate_type_is_enum(typeIndex): return self.constructEnumTypeDescriptor(typeIndex) elif interrogate_type_is_wrapped(typeIndex): if interrogate_type_is_pointer(typeIndex): return self.constructPointerTypeDescriptor(typeIndex) elif interrogate_type_is_const(typeIndex): return self.constructConstTypeDescriptor(typeIndex) elif (interrogate_type_is_class(typeIndex) or interrogate_type_is_struct(typeIndex) or interrogate_type_is_union(typeIndex)): return self.constructClassTypeDescriptor(typeIndex) elif (not interrogate_type_is_fully_defined(typeIndex)): return self.constructClassTypeDescriptor(typeIndex) else: raise 'A type in the interrogate database was not recognized: '+ repr(typeIndex) def constructPrimitiveTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] else: descriptor = FFITypes.PrimitiveTypeDescriptor() #descriptor.environment = self.environment descriptor.atomicType = interrogate_type_atomic_token(typeIndex) if interrogate_type_has_module_name(typeIndex): descriptor.moduleName = 'lib' + interrogate_type_module_name(typeIndex) descriptor.foreignTypeName = \ FFIRename.nonClassNameFromCppName(getTypeName(typeIndex)) descriptor.typeIndex = typeIndex self.typeIndexMap[typeIndex] = descriptor return descriptor def constructEnumTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] else: descriptor = FFITypes.EnumTypeDescriptor() #descriptor.environment = self.environment descriptor.isNested = interrogate_type_is_nested(typeIndex) if descriptor.isNested: outerTypeIndex = interrogate_type_outer_class(typeIndex) descriptor.outerType = self.constructDescriptor(outerTypeIndex) if interrogate_type_has_module_name(typeIndex): descriptor.moduleName = 'lib' + interrogate_type_module_name(typeIndex) # Enums are ints in C++ but we do not want to redefine the int type # So we will just call them enums descriptor.enumName = FFIRename.classNameFromCppName(getTypeName(typeIndex)) descriptor.foreignTypeName = '__enum__' + descriptor.enumName numValues = interrogate_type_number_of_enum_values(typeIndex) # Store the names and values of the enum in a dictionary for i in range(numValues): value = interrogate_type_enum_value(typeIndex, i) name = FFIRename.classNameFromCppName( interrogate_type_enum_value_name(typeIndex, i)) scopedName = FFIRename.classNameFromCppName( interrogate_type_enum_value_scoped_name(typeIndex, i)) descriptor.values[name] = value descriptor.typeIndex = typeIndex self.typeIndexMap[typeIndex] = descriptor return descriptor def constructPointerTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] descriptor = FFITypes.PointerTypeDescriptor() #descriptor.environment = self.environment descriptor.isNested = interrogate_type_is_nested(typeIndex) if descriptor.isNested: outerTypeIndex = interrogate_type_outer_class(typeIndex) descriptor.outerType = self.constructDescriptor(outerTypeIndex) if interrogate_type_has_module_name(typeIndex): descriptor.moduleName = 'lib' + interrogate_type_module_name(typeIndex) descriptor.foreignTypeName = \ FFIRename.nonClassNameFromCppName(getTypeName(typeIndex)) descriptor.typeIndex = typeIndex wrappedTypeIndex = interrogate_type_wrapped_type(typeIndex) wrappedTypeDescriptor = self.constructDescriptor(wrappedTypeIndex) descriptor.typeDescriptor = wrappedTypeDescriptor self.typeIndexMap[typeIndex] = descriptor return descriptor def constructConstTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] descriptor = FFITypes.ConstTypeDescriptor() #descriptor.environment = self.environment descriptor.isNested = interrogate_type_is_nested(typeIndex) if descriptor.isNested: outerTypeIndex = interrogate_type_outer_class(typeIndex) descriptor.outerType = self.constructDescriptor(outerTypeIndex) if interrogate_type_has_module_name(typeIndex): descriptor.moduleName = 'lib' + interrogate_type_module_name(typeIndex) descriptor.foreignTypeName = \ FFIRename.nonClassNameFromCppName(getTypeName(typeIndex)) descriptor.typeIndex = typeIndex wrappedTypeIndex = interrogate_type_wrapped_type(typeIndex) wrappedTypeDescriptor = self.constructDescriptor(wrappedTypeIndex) descriptor.typeDescriptor = wrappedTypeDescriptor self.typeIndexMap[typeIndex] = descriptor return descriptor def constructParentTypeDescriptors(self, typeIndex): numParents = interrogate_type_number_of_derivations(typeIndex) descriptors = [] for i in range(numParents): parentTypeIndex = interrogate_type_get_derivation(typeIndex, i) if self.isDefinedType(parentTypeIndex): parentTypeDescriptor = self.typeIndexMap[parentTypeIndex] else: parentTypeDescriptor = self.constructDescriptor(parentTypeIndex) descriptors.append(parentTypeDescriptor) return descriptors def constructNestedTypeDescriptors(self, typeIndex): nestedTypes = [] numNestedTypes = interrogate_type_number_of_nested_types(typeIndex) for i in range(numNestedTypes): nestedTypeIndex = interrogate_type_get_nested_type(typeIndex, i) descriptor = self.constructDescriptor(nestedTypeIndex) nestedTypes.append(descriptor) return nestedTypes def constructClassTypeDescriptor(self, typeIndex): if self.isDefinedType(typeIndex): return self.typeIndexMap[typeIndex] typeName = FFIRename.classNameFromCppName(getTypeName(typeIndex)) if typeName == "PyObject": # A special case: the PyObject type is really a native # Python object, not to be molested--it's not really an # FFI class object. descriptor = FFITypes.PyObjectTypeDescriptor() self.typeIndexMap[typeIndex] = descriptor return descriptor descriptor = FFITypes.ClassTypeDescriptor() self.typeIndexMap[typeIndex] = descriptor #descriptor.environment = self.environment descriptor.foreignTypeName = typeName if (typeName == "TypedObject"): FFITypes.TypedObjectDescriptor = descriptor descriptor.isNested = interrogate_type_is_nested(typeIndex) if descriptor.isNested: outerTypeIndex = interrogate_type_outer_class(typeIndex) descriptor.outerType = self.constructDescriptor(outerTypeIndex) if interrogate_type_has_module_name(typeIndex): descriptor.moduleName = 'lib' + interrogate_type_module_name(typeIndex) if FFIConstants.wantComments: if interrogate_type_has_comment(typeIndex): descriptor.comment = interrogate_type_comment(typeIndex) descriptor.typeIndex = typeIndex descriptor.instanceMethods = self.constructMemberFunctionSpecifications(typeIndex) descriptor.upcastMethods = self.constructUpcastFunctionSpecifications(typeIndex) # Constructing downcasts does not return the functions, it just puts them in the class # See the comment in that function self.constructDowncastFunctionSpecifications(typeIndex) descriptor.filterOutStaticMethods() descriptor.constructors = self.constructConstructorSpecifications(typeIndex) descriptor.destructor = self.constructDestructorSpecification(typeIndex) descriptor.parentTypes = self.constructParentTypeDescriptors(typeIndex) descriptor.nestedTypes = self.constructNestedTypeDescriptors(typeIndex) return descriptor def constructFunctionTypeDescriptors(self, functionIndex): # Store these values because they will be the same for all the wrappers isVirtual = interrogate_function_is_virtual(functionIndex) #environment = self.environment foreignTypeName = interrogate_function_name(functionIndex) if FFIConstants.wantComments: prototype = interrogate_function_prototype(functionIndex) if interrogate_function_has_comment(functionIndex): comment = interrogate_function_comment(functionIndex) else: comment = '' # Prepend lib to the module name it reports because that will be the name of # the Python module we import. This is apparently stems from a makefile # discrepency in the way we build the libraries if interrogate_function_has_module_name(functionIndex): moduleName = 'lib' + interrogate_function_module_name(functionIndex) else: moduleName = None typeIndex = functionIndex # Look at the Python wrappers for this function numPythonWrappers = interrogate_function_number_of_python_wrappers(functionIndex) if numPythonWrappers == 0: # If there are no Python wrappers, it is because interrogate could not handle # something about the function. Just return an empty list return [] wrapperDescriptors = [] # Iterate over the wrappers constructing a FunctionTypeDescriptor for each for i in range(numPythonWrappers): descriptor = FFITypes.FunctionTypeDescriptor() descriptor.isVirtual = isVirtual #descriptor.environment = environment descriptor.foreignTypeName = foreignTypeName if FFIConstants.wantComments: descriptor.comment = comment descriptor.prototype = prototype descriptor.moduleName = moduleName descriptor.typeIndex = typeIndex pythonFunctionIndex = interrogate_function_python_wrapper(functionIndex, i) descriptor.wrapperName = interrogate_wrapper_name(pythonFunctionIndex) # Even if it does not have a return value, it reports void which is better # for generating code, so I will not even ask here # if interrogate_wrapper_has_return_value(pythonFunctionIndex): returnType = interrogate_wrapper_return_type(pythonFunctionIndex) descriptor.returnType = self.constructDescriptor(returnType) descriptor.argumentTypes = self.constructFunctionArgumentTypes(pythonFunctionIndex) descriptor.userManagesMemory = interrogate_wrapper_caller_manages_return_value(pythonFunctionIndex) descriptor.returnValueDestructor = interrogate_wrapper_return_value_destructor(pythonFunctionIndex) wrapperDescriptors.append(descriptor) return wrapperDescriptors def constructFunctionArgumentTypes(self, functionIndex): numArgs = interrogate_wrapper_number_of_parameters(functionIndex) arguments = [] for argIndex in range(numArgs): if interrogate_wrapper_parameter_has_name(functionIndex, argIndex): name = FFIRename.nonClassNameFromCppName( interrogate_wrapper_parameter_name(functionIndex, argIndex)) else: name = ('parameter' + repr(argIndex)) descriptor = self.constructDescriptor( interrogate_wrapper_parameter_type(functionIndex, argIndex)) argSpec = FFISpecs.MethodArgumentSpecification() if interrogate_wrapper_parameter_is_this(functionIndex, argIndex): argSpec.isThis = 1 argSpec.name = name argSpec.typeDescriptor = descriptor arguments.append(argSpec) return arguments def constructMemberFunctionSpecifications(self, typeIndex): funcSpecs = [] numFuncs = interrogate_type_number_of_methods(typeIndex) for i in range(numFuncs): funcIndex = interrogate_type_get_method(typeIndex, i) typeDescs = self.constructFunctionTypeDescriptors(funcIndex) for typeDesc in typeDescs: funcSpec = FFISpecs.MethodSpecification() funcSpec.name = FFIRename.methodNameFromCppName( interrogate_function_name(funcIndex), getTypeName(typeIndex)) funcSpec.typeDescriptor = typeDesc funcSpec.index = funcIndex funcSpecs.append(funcSpec) return funcSpecs def constructUpcastFunctionSpecifications(self, typeIndex): funcSpecs = [] numFuncs = interrogate_type_number_of_derivations(typeIndex) for i in range(numFuncs): if interrogate_type_derivation_has_upcast(typeIndex, i): funcIndex = interrogate_type_get_upcast(typeIndex, i) typeDescs = self.constructFunctionTypeDescriptors(funcIndex) for typeDesc in typeDescs: funcSpec = FFISpecs.MethodSpecification() # We synthesize the upcast function name instead # of using the name supplied by interrogate, to # allow for possible renaming of types on this # side. funcSpec.name = 'upcastTo' + typeDesc.returnType.typeDescriptor.foreignTypeName #funcSpec.name = FFIRename.methodNameFromCppName( # interrogate_function_name(funcIndex)) funcSpec.typeDescriptor = typeDesc funcSpec.index = funcIndex funcSpecs.append(funcSpec) return funcSpecs def constructDowncastFunctionSpecifications(self, typeIndex): """ The strange thing about downcast functions is that they appear in the class they are being downcast TO, not downcast FROM. But they should be built into the class they are being downcast from. For instance, a method downcastToNode(ptrBoundedObject) will appear in Node's list of methods but should be compiled into BoundedObject's class UPDATE: These are no longer compiled into the from-class. That was preventing the libraries from being independent since the from class now had knowledge of the to class which is potentially in a library downstream. Now these functions are just global functions """ numFuncs = interrogate_type_number_of_derivations(typeIndex) for i in range(numFuncs): # Make sure this downcast is possible if (not interrogate_type_derivation_downcast_is_impossible(typeIndex, i)): if interrogate_type_derivation_has_downcast(typeIndex, i): funcIndex = interrogate_type_get_downcast(typeIndex, i) typeDescs = self.constructFunctionTypeDescriptors(funcIndex) for typeDesc in typeDescs: funcSpec = FFISpecs.GlobalFunctionSpecification() funcSpec.name = FFIRename.methodNameFromCppName( interrogate_function_name(funcIndex), getTypeName(typeIndex)) funcSpec.typeDescriptor = typeDesc funcSpec.index = funcIndex # Here we look for the class in the first argument fromClass = typeDesc.argumentTypes[0].typeDescriptor.recursiveTypeDescriptor() # Append the from class name on the method to uniquify it now # that these are global methods funcSpec.name = funcSpec.name + 'From' + fromClass.foreignTypeName # Append this funcSpec to that class's downcast methods # fromClass.downcastMethods.append(funcSpec) self.environment.addDowncastFunction(funcSpec) def constructConstructorSpecifications(self, typeIndex): funcSpecs = [] numFuncs = interrogate_type_number_of_constructors(typeIndex) for i in range(numFuncs): funcIndex = interrogate_type_get_constructor(typeIndex, i) typeDescs = self.constructFunctionTypeDescriptors(funcIndex) for typeDesc in typeDescs: funcSpec = FFISpecs.MethodSpecification() funcSpec.name = 'constructor' # funcSpec.name = FFIRename.methodNameFromCppName( # interrogate_function_name(funcIndex)) funcSpec.typeDescriptor = typeDesc # Flag this function as being a constructor funcSpec.constructor = 1 funcSpec.index = funcIndex funcSpecs.append(funcSpec) return funcSpecs def constructDestructorSpecification(self, typeIndex): if (not interrogate_type_has_destructor(typeIndex)): return None funcIndex = interrogate_type_get_destructor(typeIndex) typeDescs = self.constructFunctionTypeDescriptors(funcIndex) if (len(typeDescs) == 0): return None for typeDesc in typeDescs: funcSpec = FFISpecs.MethodSpecification() funcSpec.name = 'destructor' # funcSpec.name = FFIRename.methodNameFromCppName( # interrogate_function_name(funcIndex)) funcSpec.typeDescriptor = typeDesc funcSpec.index = funcIndex return funcSpec def addTypes(self, CModuleName): for i in range(interrogate_number_of_global_types()): typeIndex = interrogate_get_global_type(i) if self.typeInCModule(typeIndex, CModuleName): self.constructDescriptor(typeIndex) def addEnvironmentTypes(self): for descriptor in self.typeIndexMap.values(): self.environment.addType(descriptor, descriptor.foreignTypeName) def functionInCModule(self, funcIndex, CModuleName): if interrogate_function_has_module_name(funcIndex): moduleName = 'lib' + interrogate_function_module_name(funcIndex) return (moduleName == CModuleName) def typeInCModule(self, typeIndex, CModuleName): if interrogate_type_has_module_name(typeIndex): moduleName = 'lib' + interrogate_type_module_name(typeIndex) return (moduleName == CModuleName) def constructGlobal(self, globalIndex, CModuleName): # We really do not need the descriptor for the value, just # the getter and setter # typeIndex = interrogate_element_type(globalIndex) # descriptor = self.constructDescriptor(typeIndex) if interrogate_element_has_getter(globalIndex): getterIndex = interrogate_element_getter(globalIndex) # If this function is not in this Cmodule just return if not self.functionInCModule(getterIndex, CModuleName): return None getter = self.constructGlobalFunction(getterIndex) else: getter = None if interrogate_element_has_setter(globalIndex): setterIndex = interrogate_element_setter(globalIndex) # If this function is not in this Cmodule just return if not self.functionInCModule(setterIndex, CModuleName): return None setter = self.constructGlobalFunction(setterIndex) else: setter = None globalSpec = FFISpecs.GlobalValueSpecification() globalSpec.getter = getter globalSpec.setter = setter # globalSpec.typeDescriptor = descriptor cppName = interrogate_element_name(globalIndex) globalSpec.name = FFIRename.classNameFromCppName(cppName) return globalSpec def constructGlobalFunction(self, globalIndex): descriptors = self.constructFunctionTypeDescriptors(globalIndex) if (len(descriptors) == 0): return None funcSpecs = [] for descriptor in descriptors: funcSpec = FFISpecs.GlobalFunctionSpecification() funcSpec.typeDescriptor = descriptor funcSpec.name = FFIRename.methodNameFromCppName( funcSpec.typeDescriptor.foreignTypeName) funcSpec.index = globalIndex funcSpecs.append(funcSpec) return funcSpecs def addGlobalFunctions(self, CModuleName): numGlobals = interrogate_number_of_global_functions() for i in range(numGlobals): funcIndex = interrogate_get_global_function(i) if self.functionInCModule(funcIndex, CModuleName): newGlob = self.constructGlobalFunction(funcIndex) if newGlob: self.environment.addGlobalFunction(newGlob) def addGlobalValues(self, CModuleName): numGlobals = interrogate_number_of_globals() for i in range(numGlobals): globalIndex = interrogate_get_global(i) newGlob = self.constructGlobal(globalIndex, CModuleName) if newGlob: self.environment.addGlobalValue(newGlob) def constructManifest(self, manifestIndex): descriptor = None intValue = None getter = None if interrogate_manifest_has_type(manifestIndex): typeIndex = interrogate_manifest_get_type(manifestIndex) descriptor = self.constructDescriptor(typeIndex) definition = interrogate_manifest_definition(manifestIndex) # See if this manifest is an int. There are shortcuts if it is. # If it does have an int value, there will be no getter, we will # just output the value in the generated code if interrogate_manifest_has_int_value(manifestIndex): intValue = interrogate_manifest_get_int_value(manifestIndex) else: # See if this manifest has a getter if interrogate_manifest_has_getter(manifestIndex): getterIndex = interrogate_manifest_getter(manifestIndex) getter = self.constructGlobalFunction(getterIndex) manifestSpec = FFISpecs.ManifestSpecification() manifestSpec.typeDescriptor = descriptor manifestSpec.definition = definition manifestSpec.intValue = intValue manifestSpec.getter = getter cppName = interrogate_manifest_name(manifestIndex) manifestSpec.name = FFIRename.classNameFromCppName(cppName) return manifestSpec def addManifestSymbols(self): numManifests = interrogate_number_of_manifests() for i in range(numManifests): manifestIndex = interrogate_get_manifest(i) newManifest = self.constructManifest(manifestIndex) self.environment.addManifest(newManifest) def generateCode(self, codeDir, extensionsDir): # Empty out the codeDir of unnecessary crud from previous runs # before we begin. for file in os.listdir(codeDir): pathname = os.path.join(codeDir, file) if not os.path.isdir(pathname): os.unlink(pathname) # Import all the C++ modules for CModuleName in FFIConstants.CodeModuleNameList: self.generateCodeLib(codeDir, extensionsDir, CModuleName) # For convenience, output a file that imports all the c module files file = open(os.path.join(codeDir, FFIConstants.importModuleName + '.py'), 'w') for CModuleName in FFIConstants.CodeModuleNameList: file.write('from ' + CModuleName + 'Modules import *\n') file.close() # Generate an empty __init__.py to make the directory a Python # package. init = os.path.join(codeDir, '__init__.py') file = open(init, 'w') file.close() def squeezeGeneratedCode(self, outputDir, deleteSource=True): # Since we will be squeezing the importModuleName file, rename # the original to something we can import from within the # squeezed version. squeezedName = FFIConstants.importModuleName unsqueezedName = FFIConstants.importModuleName + 'Unsqueezed' os.rename(os.path.join(outputDir, squeezedName + '.py'), os.path.join(outputDir, unsqueezedName + '.py')) # Get the list of files to squeeze. This is all of the .py # files in the output directory except for the __init__.py # file. files = glob.glob(os.path.join(outputDir, '*.py')) init = os.path.join(outputDir, '__init__.py') try: files.remove(init) except: pass print "Squeezing %s files." % (len(files)) from direct.showbase import pandaSqueezeTool pandaSqueezeTool.squeeze(squeezedName, unsqueezedName, files, outputDir) if deleteSource: # Remove the now-squeezed source files. for file in files: os.remove(file) def generateCodeLib(self, codeDir, extensionsDir, CModuleName): # Reset the environment so we are clean from any old modules self.environment.reset() FFIConstants.notify.info('='*50) FFIConstants.notify.warning('Importing code library: ' + CModuleName) exec('import ' + CModuleName) if interrogate_error_flag(): FFIConstants.notify.error("Error reading interrogate database; can't continue.") self.updateBindings(CModuleName) FFIConstants.notify.info('Generating type code...') for type in self.environment.types.values(): # Do not generate code for nested types at the top level if (not type.isNested): type.generateGlobalCode(codeDir, extensionsDir) FFIConstants.notify.info('Generating global downcast code...') downcastFile = constructDowncastFile(codeDir, CModuleName) # Output all the imports based on this list of functions outputGlobalFileImports(downcastFile, self.environment.downcastFunctions, CModuleName) for type in self.environment.downcastFunctions: type.generateGlobalDowncastCode(downcastFile) FFIConstants.notify.info('Generating global code...') globalFile = constructGlobalFile(codeDir, CModuleName) # Make a list of all the global functions. This includes the normal # global functions as well as the getters and setters on all the # global values. This list is used to figure out what files to import # Only include the global functions from the current C module globalFunctions = self.environment.globalFunctions for globalValue in self.environment.globalValues: if globalValue.getter: globalFunctions.append(globalValue.getter) if globalValue.setter: globalFunctions.append(globalValue.setter) # Output all the imports based on this list of functions outputGlobalFileImports(globalFile, globalFunctions, CModuleName) # Generate overloading overloadedGlobalFunctions = {} for methodSpec in globalFunctions: methodList = overloadedGlobalFunctions.setdefault(methodSpec.name, []) methodList.append(methodSpec) overloadedGlobalFunctions = FFIOverload.cullOverloadedMethods(overloadedGlobalFunctions) for methodSpecList in overloadedGlobalFunctions.values(): treeColl = FFIOverload.FFIMethodArgumentTreeCollection(None, methodSpecList) treeColl.generateCode(globalFile, -1) FFIConstants.notify.info('Generating global values...') for type in self.environment.globalValues: type.generateGlobalCode(globalFile) FFIConstants.notify.info('Generating global functions...') for type in self.environment.globalFunctions: type.generateGlobalCode(globalFile) FFIConstants.notify.info('Generating manifests...') for type in self.environment.manifests: type.generateGlobalCode(globalFile) globalFile.close() FFIConstants.notify.info('Generating import code...') importFile = constructImportFile(codeDir, CModuleName) outputImportFileImports(importFile, self.environment.types.values(), CModuleName) def updateBindings(self, CModuleName): FFIConstants.notify.info('Updating Bindings') FFIConstants.notify.info('Adding Types...') self.addTypes(CModuleName) FFIConstants.notify.info('Adding global values...') self.addGlobalValues(CModuleName) FFIConstants.notify.info('Adding global functions...') self.addGlobalFunctions(CModuleName) FFIConstants.notify.info('Adding manifests symbols...') self.addManifestSymbols() FFIConstants.notify.info('Adding environment types...') self.addEnvironmentTypes()