*** empty log message ***

This commit is contained in:
Joe Shochet 2000-11-07 21:49:37 +00:00
parent 1f4c504b42
commit 0901fd9c20
8 changed files with 244 additions and 132 deletions

View File

@ -3,10 +3,6 @@
from DirectNotifyGlobal import * from DirectNotifyGlobal import *
notify = directNotify.newCategory("FFI") notify = directNotify.newCategory("FFI")
# This is the name of the file that the global functions and values
# will be stored
globalModuleName = 'PandaGlobals'
# This is the name of the file that the importing code will be stored # This is the name of the file that the importing code will be stored
importModuleName = 'PandaModules' importModuleName = 'PandaModules'

View File

@ -2,8 +2,12 @@ import FFIConstants
class FFIEnvironment: class FFIEnvironment:
def __init__(self): def __init__(self):
self.reset()
def reset(self):
self.types = {} self.types = {}
self.globalFunctions = [] self.globalFunctions = []
self.downcastFunctions = []
self.globalValues = [] self.globalValues = []
self.manifests = [] self.manifests = []
@ -20,6 +24,8 @@ class FFIEnvironment:
def addGlobalFunction(self, typeDescriptor): def addGlobalFunction(self, typeDescriptor):
self.globalFunctions.append(typeDescriptor) self.globalFunctions.append(typeDescriptor)
def addDowncastFunction(self, typeDescriptor):
self.downcastFunctions.append(typeDescriptor)
def addGlobalValue(self, typeDescriptor): def addGlobalValue(self, typeDescriptor):
self.globalValues.append(typeDescriptor) self.globalValues.append(typeDescriptor)
def addManifest(self, typeDescriptor): def addManifest(self, typeDescriptor):

View File

@ -4,26 +4,19 @@ import TypedObject
WrapperClassMap = {} WrapperClassMap = {}
# For testing, you can turn verbose and debug on
FFIConstants.notify.setVerbose(1)
FFIConstants.notify.setDebug(1)
def getDowncastFunctions(thisClass, baseClass, chain): # Register a python class in the type map if it is a typed object
if (thisClass == baseClass): # The type map is used for upcasting and downcasting through
# Found it, return true # the panda inheritance chain
return 1 def registerInTypeMap(pythonClass):
elif (len(thisClass.__bases__) == 0): if issubclass(pythonClass, TypedObject.TypedObject):
# Not here, return 0 typeIndex = pythonClass.getClassType().getIndex()
return 0 WrapperClassMap[typeIndex] = pythonClass
else:
# Look recursively in the classes thisClass inherits from
for base in thisClass.__bases__:
# If it finds it, append the base class's downcast function
# to the chain if it has one
if getDowncastFunctions(base, baseClass, chain):
downcastFuncName = 'downcastTo' + thisClass.__name__
if base.__dict__.has_key(downcastFuncName):
FFIConstants.notify.debug('Found downcast function %s in %s' % (downcastFuncName, base.__name__))
chain.append(base.__dict__[downcastFuncName])
return chain
class FFIExternalObject: class FFIExternalObject:
@ -32,23 +25,52 @@ class FFIExternalObject:
self.userManagesMemory = 0 self.userManagesMemory = 0
# Start with a null this pointer # Start with a null this pointer
self.this = 0 self.this = 0
def getDowncastFunctions(self, thisClass, baseClass, chain):
if (thisClass == baseClass):
# Found it, return true
return 1
elif (len(thisClass.__bases__) == 0):
# Not here, return 0
return 0
else:
# Look recursively in the classes thisClass inherits from
for base in thisClass.__bases__:
# If it finds it, append the base class's downcast function
# to the chain if it has one
if self.getDowncastFunctions(base, baseClass, chain):
downcastFuncName = ('downcastTo' + thisClass.__name__
+ 'From' + base.__name__)
# Look over this classes global modules dictionaries
# for the downcast function name
for globmod in self.__class__.__CModuleDowncasts__:
if globmod.__dict__.has_key(downcastFuncName):
func = globmod.__dict__[downcastFuncName]
FFIConstants.notify.debug('Found downcast function %s in %s'
% (downcastFuncName, globmod.__name__))
chain.append(func)
return chain
else:
FFIConstants.notify.debug('Did not find downcast function %s in %s'
% (downcastFuncName, globmod.__name__))
# In any case, return the chain
return chain
# Probably went up the wrong tree and did not find the rootClass
else:
return []
def asExactType(self):
return self.getType()
def isTypedObject(self):
return isinstance(self, TypedObject.TypedObject)
def setPointer(self): def setPointer(self):
if (self.this == 0): if (self.this == 0):
# Null pointer, return None # Null pointer, return None
return None return None
# If it is not a typed object, our work is done, just return the object # If it is not a typed object, our work is done, just return the object
if (not self.isTypedObject()): if (not isinstance(self, TypedObject.TypedObject)):
return self return self
# Ok, it is a typed object. See what type it really is and downcast # Ok, it is a typed object. See what type it really is and downcast
# to that type (if necessary) # to that type (if necessary)
exactWrapperClass = self.wrapperClassForTypeHandle(self.asExactType()) exactWrapperClass = self.wrapperClassForTypeHandle(self.getType())
# We do not need to downcast if we already have the same class # We do not need to downcast if we already have the same class
if (exactWrapperClass and (exactWrapperClass != self.__class__)): if (exactWrapperClass and (exactWrapperClass != self.__class__)):
# Create a new wrapper class instance # Create a new wrapper class instance
@ -71,16 +93,10 @@ class FFIExternalObject:
else: else:
return None return None
def registerInTypeMap(self):
global WrapperClassMap
if self.isTypedObject():
typeIndex = self.__class__.getClassType().getIndex()
WrapperClassMap[typeIndex] = self.__class__
def downcast(self, specificClass): def downcast(self, specificClass):
FFIConstants.notify.debug('downcasting from %s to %s' % \ FFIConstants.notify.debug('downcasting from %s to %s' % \
(self.__class__.__name__, specificClass.__name__)) (self.__class__.__name__, specificClass.__name__))
downcastChain = getDowncastFunctions(specificClass, self.__class__, []) downcastChain = self.getDowncastFunctions(specificClass, self.__class__, [])
FFIConstants.notify.debug('downcast chain: ' + `downcastChain`) FFIConstants.notify.debug('downcast chain: ' + `downcastChain`)
newObject = self newObject = self
if (downcastChain == None): if (downcastChain == None):
@ -124,7 +140,4 @@ class FFIExternalObject:

View File

@ -21,26 +21,30 @@ FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.Interr
# to be dependent on the name of the interrogate library in this code # to be dependent on the name of the interrogate library in this code
exec('from ' + FFIConstants.InterrogateModuleName + ' import *') exec('from ' + FFIConstants.InterrogateModuleName + ' import *')
# Import all the C++ modules def constructGlobalFile(codeDir, CModuleName):
for CModuleName in FFIConstants.CodeModuleNameList:
FFIConstants.notify.info('Importing code library: ' + CModuleName)
exec('import ' + CModuleName)
def constructGlobalFile(codeDir):
""" """
Open a file that will hold the global values and functions code Open a file that will hold the global values and functions code
""" """
file = open(os.path.join(codeDir, FFIConstants.globalModuleName + '.py'), 'w') file = open(os.path.join(codeDir, CModuleName + 'Globals' + '.py'), 'w')
return file return file
def constructImportFile(codeDir):
def constructDowncastFile(codeDir, CModuleName):
""" """
Open a file that will hold the global values and functions code Open a file that will hold the global values and functions code
""" """
file = open(os.path.join(codeDir, FFIConstants.importModuleName + '.py'), 'w') file = open(os.path.join(codeDir, CModuleName + 'Downcasts' + '.py'), 'w')
return file return file
def outputGlobalFileImports(file, methodList):
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 # Print the standard header
file.write(FFIConstants.generatedHeader) file.write(FFIConstants.generatedHeader)
@ -48,15 +52,34 @@ def outputGlobalFileImports(file, methodList):
file.write('import types\n') file.write('import types\n')
# Import the C modules # Import the C modules
for CModuleName in FFIConstants.CodeModuleNameList: CModuleList = []
for method in methodList:
if (not (method.typeDescriptor.moduleName in CModuleList)):
CModuleList.append(method.typeDescriptor.moduleName)
for CModuleName in CModuleList:
file.write('import ' + CModuleName + '\n') file.write('import ' + CModuleName + '\n')
moduleList = [] moduleList = []
for method in methodList: for method in methodList:
returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor() returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor()
if (not (returnType.foreignTypeName in moduleList)): returnTypeName = returnType.foreignTypeName
if (not (returnTypeName in moduleList)):
if (returnType.__class__ == FFITypes.ClassTypeDescriptor): if (returnType.__class__ == FFITypes.ClassTypeDescriptor):
moduleList.append(returnType.foreignTypeName) 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()
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: for moduleName in moduleList:
file.write('import ' + moduleName + '\n') file.write('import ' + moduleName + '\n')
@ -64,7 +87,7 @@ def outputGlobalFileImports(file, methodList):
file.write('\n') file.write('\n')
def outputImportFileImports(file, typeList): def outputImportFileImports(file, typeList, CModuleName):
""" """
This is the file that we will import to get all the panda modules This is the file that we will import to get all the panda modules
""" """
@ -76,10 +99,8 @@ def outputImportFileImports(file, typeList):
file.write('import ' + FFIConstants.InterrogateModuleName + '\n') file.write('import ' + FFIConstants.InterrogateModuleName + '\n')
file.write('\n') file.write('\n')
file.write('# Import the C modules\n') file.write('# Import the C module\n')
for CModuleName in FFIConstants.CodeModuleNameList: file.write('import ' + CModuleName + '\n')
file.write('import ' + CModuleName + '\n')
file.write('\n')
# Filter out only the class and enum type descriptors (not const, pointers, etc) # Filter out only the class and enum type descriptors (not const, pointers, etc)
classTypeList = [] classTypeList = []
@ -96,12 +117,9 @@ def outputImportFileImports(file, typeList):
classTypeList.sort(FFIOverload.inheritanceLevelSort) classTypeList.sort(FFIOverload.inheritanceLevelSort)
moduleList = [] moduleList = []
for type in classTypeList: for type in classTypeList:
moduleList.append(type.foreignTypeName) moduleList.append(type.foreignTypeName)
file.write('import FFIExternalObject\n')
file.write('\n')
file.write('# Import enums into the global name space\n') file.write('# Import enums into the global name space\n')
for type in enumTypeList: for type in enumTypeList:
file.write('from ' + type.enumName + ' import *\n') file.write('from ' + type.enumName + ' import *\n')
@ -113,25 +131,28 @@ def outputImportFileImports(file, typeList):
file.write('\n') file.write('\n')
file.write('# Import the global module file into our name space\n') file.write('# Import the global module file into our name space\n')
file.write('from ' + FFIConstants.globalModuleName + ' import *\n') file.write('from ' + CModuleName + 'Globals' + ' import *\n')
file.write('\n') file.write('\n')
file.write('# Now generate the classes\n') file.write('# Generate the classes\n')
for moduleName in moduleList: for moduleName in moduleList:
file.write(moduleName + '.generateClass_' + moduleName + '()\n') file.write(moduleName + '.generateClass_' + moduleName + '()\n')
file.write('\n') file.write('\n')
file.write('# Now put the classes in the wrapper class map\n') file.write('# Copy the classes into our own namespace\n')
for moduleName in moduleList:
file.write('obj = ' + moduleName + '.' + moduleName + '(None)\n')
file.write('obj.registerInTypeMap()\n')
file.write('\n')
file.write('# Now copy the classes into our own namespace\n')
for moduleName in moduleList: for moduleName in moduleList:
file.write(moduleName + ' = ' + moduleName + '.' + moduleName + '\n') file.write(moduleName + ' = ' + moduleName + '.' + moduleName + '\n')
file.write('\n') file.write('\n')
file.write('# Put the classes in the wrapper class map\n')
file.write('from FFIExternalObject import registerInTypeMap\n')
file.write('\n')
for moduleName in moduleList:
file.write('registerInTypeMap(' + moduleName + ')\n')
file.write('\n')
def generateStaticClass(codeDir): def generateStaticClass(codeDir):
""" """
Create a file that will hold the static class definition Create a file that will hold the static class definition
@ -472,6 +493,10 @@ class FFIInterrogateDatabase:
built into the class they are being downcast from. For instance, a method built into the class they are being downcast from. For instance, a method
downcastToNode(ptrBoundedObject) will appear in Node's list of methods downcastToNode(ptrBoundedObject) will appear in Node's list of methods
but should be compiled into BoundedObject's class 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) numFuncs = interrogate_type_number_of_derivations(typeIndex)
for i in range(numFuncs): for i in range(numFuncs):
@ -481,15 +506,21 @@ class FFIInterrogateDatabase:
funcIndex = interrogate_type_get_downcast(typeIndex, i) funcIndex = interrogate_type_get_downcast(typeIndex, i)
typeDescs = self.constructFunctionTypeDescriptors(funcIndex) typeDescs = self.constructFunctionTypeDescriptors(funcIndex)
for typeDesc in typeDescs: for typeDesc in typeDescs:
funcSpec = FFISpecs.MethodSpecification() funcSpec = FFISpecs.GlobalFunctionSpecification()
funcSpec.name = FFIRename.methodNameFromCppName( funcSpec.name = FFIRename.methodNameFromCppName(
interrogate_function_name(funcIndex)) interrogate_function_name(funcIndex))
funcSpec.typeDescriptor = typeDesc funcSpec.typeDescriptor = typeDesc
funcSpec.index = funcIndex funcSpec.index = funcIndex
# Here we look for the class in the first argument # Here we look for the class in the first argument
fromClass = typeDesc.argumentTypes[0].typeDescriptor.recursiveTypeDescriptor() 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 # Append this funcSpec to that class's downcast methods
fromClass.downcastMethods.append(funcSpec) # fromClass.downcastMethods.append(funcSpec)
self.environment.addDowncastFunction(funcSpec)
def constructConstructorSpecifications(self, typeIndex): def constructConstructorSpecifications(self, typeIndex):
funcSpecs = [] funcSpecs = []
@ -532,8 +563,14 @@ class FFIInterrogateDatabase:
def addEnvironmentTypes(self): def addEnvironmentTypes(self):
for descriptor in self.typeIndexMap.values(): for descriptor in self.typeIndexMap.values():
self.environment.addType(descriptor, descriptor.foreignTypeName) 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 constructGlobal(self, globalIndex): def constructGlobal(self, globalIndex, CModuleName):
# We really do not need the descriptor for the value, just # We really do not need the descriptor for the value, just
# the getter and setter # the getter and setter
# typeIndex = interrogate_element_type(globalIndex) # typeIndex = interrogate_element_type(globalIndex)
@ -541,12 +578,18 @@ class FFIInterrogateDatabase:
if interrogate_element_has_getter(globalIndex): if interrogate_element_has_getter(globalIndex):
getterIndex = interrogate_element_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) getter = self.constructGlobalFunction(getterIndex)
else: else:
getter = None getter = None
if interrogate_element_has_setter(globalIndex): if interrogate_element_has_setter(globalIndex):
setterIndex = interrogate_element_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) setter = self.constructGlobalFunction(setterIndex)
else: else:
setter = None setter = None
@ -570,21 +613,23 @@ class FFIInterrogateDatabase:
funcSpec.index = globalIndex funcSpec.index = globalIndex
return funcSpec return funcSpec
def addGlobalFunctions(self): def addGlobalFunctions(self, CModuleName):
numGlobals = interrogate_number_of_global_functions() numGlobals = interrogate_number_of_global_functions()
for i in range(numGlobals): for i in range(numGlobals):
funcIndex = interrogate_get_global_function(i) funcIndex = interrogate_get_global_function(i)
newGlob = self.constructGlobalFunction(funcIndex) if self.functionInCModule(funcIndex, CModuleName):
if newGlob: newGlob = self.constructGlobalFunction(funcIndex)
self.environment.addGlobalFunction(newGlob) if newGlob:
self.environment.addGlobalFunction(newGlob)
"""
# Take all the global functions that have a Panda Class as their # Take all the global functions that have a Panda Class as their
# first argument and make them class methods on that class # first argument and make them class methods on that class
# For example the global function # For example the global function
# get_distance(node1, node2) # get_distance(node1, node2)
# becomes: # becomes:
# node1.getDistance(node2) # node1.getDistance(node2)
# Functions that do not get moved will be stored here temporarily # Functions that do not get moved will be stored here temporarily
tempGlobalFunctions = [] tempGlobalFunctions = []
for funcSpec in self.environment.globalFunctions: for funcSpec in self.environment.globalFunctions:
@ -602,15 +647,17 @@ class FFIInterrogateDatabase:
else: else:
# Copy this function into the temp list # Copy this function into the temp list
tempGlobalFunctions.append(funcSpec) tempGlobalFunctions.append(funcSpec)
# Now copy the temp list back over the real list # Copy the temp list back over the real list
self.environment.globalFunctions = tempGlobalFunctions self.environment.globalFunctions = tempGlobalFunctions
"""
def addGlobalValues(self): def addGlobalValues(self, CModuleName):
numGlobals = interrogate_number_of_globals() numGlobals = interrogate_number_of_globals()
for i in range(numGlobals): for i in range(numGlobals):
globalIndex = interrogate_get_global(i) globalIndex = interrogate_get_global(i)
newGlob = self.constructGlobal(globalIndex) newGlob = self.constructGlobal(globalIndex, CModuleName)
self.environment.addGlobalValue(newGlob) if newGlob:
self.environment.addGlobalValue(newGlob)
def constructManifest(self, manifestIndex): def constructManifest(self, manifestIndex):
@ -656,18 +703,50 @@ class FFIInterrogateDatabase:
FFIConstants.notify.info( 'Generating static class...') FFIConstants.notify.info( 'Generating static class...')
generateStaticClass(codeDir) generateStaticClass(codeDir)
# 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()
FFIConstants.notify.info( 'Compiling code...')
compileall.compile_dir(codeDir)
def generateCodeLib(self, codeDir, extensionsDir, CModuleName):
# Reset the environment so we are clean from any old modules
self.environment.reset()
FFIConstants.notify.info('==================================================')
FFIConstants.notify.info('Importing code library: ' + CModuleName)
exec('import ' + CModuleName)
self.updateBindings(CModuleName)
FFIConstants.notify.info( 'Generating type code...') FFIConstants.notify.info( 'Generating type code...')
for type in self.environment.types.values(): for type in self.environment.types.values():
# Do not generate code for nested types at the top level # Do not generate code for nested types at the top level
if (not type.isNested): if (not type.isNested):
type.generateGlobalCode(codeDir, extensionsDir) 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.generateGlobalCode(downcastFile)
FFIConstants.notify.info( 'Generating global value code...') FFIConstants.notify.info( 'Generating global value code...')
globalFile = constructGlobalFile(codeDir) globalFile = constructGlobalFile(codeDir, CModuleName)
# Make a list of all the global functions. This includes the normal # 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 functions as well as the getters and setters on all the
# global values. This list is used to figure out what files to import # 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 globalFunctions = self.environment.globalFunctions
for globalValue in self.environment.globalValues: for globalValue in self.environment.globalValues:
if globalValue.getter: if globalValue.getter:
@ -675,7 +754,7 @@ class FFIInterrogateDatabase:
if globalValue.setter: if globalValue.setter:
globalFunctions.append(globalValue.setter) globalFunctions.append(globalValue.setter)
# Output all the imports based on this list of functions # Output all the imports based on this list of functions
outputGlobalFileImports(globalFile, globalFunctions) outputGlobalFileImports(globalFile, globalFunctions, CModuleName)
FFIConstants.notify.info( 'Generating global value code...') FFIConstants.notify.info( 'Generating global value code...')
for type in self.environment.globalValues: for type in self.environment.globalValues:
@ -692,21 +771,17 @@ class FFIInterrogateDatabase:
globalFile.close() globalFile.close()
FFIConstants.notify.info( 'Generating import code...') FFIConstants.notify.info( 'Generating import code...')
importFile = constructImportFile(codeDir) importFile = constructImportFile(codeDir, CModuleName)
outputImportFileImports(importFile, self.environment.types.values()) outputImportFileImports(importFile, self.environment.types.values(), CModuleName)
FFIConstants.notify.info( 'Compiling code...') def updateBindings(self, CModuleName):
compileall.compile_dir(codeDir)
def updateBindings(self):
FFIConstants.notify.info( 'Updating Bindings') FFIConstants.notify.info( 'Updating Bindings')
FFIConstants.notify.info( 'Adding Types...') FFIConstants.notify.info( 'Adding Types...')
self.addTypes() self.addTypes()
FFIConstants.notify.info( 'Adding global values...') FFIConstants.notify.info( 'Adding global values...')
self.addGlobalValues() self.addGlobalValues(CModuleName)
FFIConstants.notify.info( 'Adding global functions...') FFIConstants.notify.info( 'Adding global functions...')
self.addGlobalFunctions() self.addGlobalFunctions(CModuleName)
FFIConstants.notify.info( 'Adding manifests symbols...') FFIConstants.notify.info( 'Adding manifests symbols...')
self.addManifestSymbols() self.addManifestSymbols()
FFIConstants.notify.info( 'Adding environment types...') FFIConstants.notify.info( 'Adding environment types...')

View File

@ -235,29 +235,35 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
""" """
Return a list of all the C modules this class references Return a list of all the C modules this class references
""" """
moduleList = [] try:
for method in (self.constructors + [self.destructor] + self.instanceMethods # Prevent from doing the work twice
+ self.upcastMethods + self.downcastMethods # if CModules is already defined, just return it
+ self.staticMethods + self.globalMethods): return self.CModules
if method: except:
if (not (method.typeDescriptor.moduleName in moduleList)): # Otherwise, it must be our first time through, do the real work
moduleList.append(method.typeDescriptor.moduleName) self.CModules = []
for method in (self.constructors + [self.destructor] + self.instanceMethods
# Now look at all the methods that we might inherit if we are at + self.upcastMethods + self.downcastMethods
# a multiple inheritance node and get their C modules + self.staticMethods + self.globalMethods):
if (len(self.parentTypes) >= 2): if method:
for parentType in self.parentTypes: if (not (method.typeDescriptor.moduleName in self.CModules)):
for method in parentType.instanceMethods: self.CModules.append(method.typeDescriptor.moduleName)
if (not (method.typeDescriptor.moduleName in moduleList)):
moduleList.append(method.typeDescriptor.moduleName) # Now look at all the methods that we might inherit if we are at
for method in parentType.upcastMethods: # a multiple inheritance node and get their C modules
if (not (method.typeDescriptor.moduleName in moduleList)): if (len(self.parentTypes) >= 2):
moduleList.append(method.typeDescriptor.moduleName) for parentType in self.parentTypes:
for method in parentType.globalMethods: for method in parentType.instanceMethods:
if (not (method.typeDescriptor.moduleName in moduleList)): if (not (method.typeDescriptor.moduleName in self.CModules)):
moduleList.append(method.typeDescriptor.moduleName) self.CModules.append(method.typeDescriptor.moduleName)
for method in parentType.upcastMethods:
return moduleList if (not (method.typeDescriptor.moduleName in self.CModules)):
self.CModules.append(method.typeDescriptor.moduleName)
for method in parentType.globalMethods:
if (not (method.typeDescriptor.moduleName in self.CModules)):
self.CModules.append(method.typeDescriptor.moduleName)
return self.CModules
def getReturnTypeModules(self): def getReturnTypeModules(self):
@ -586,6 +592,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
indent(file, 0, '# Import all the C modules this class uses\n') indent(file, 0, '# Import all the C modules this class uses\n')
for moduleName in self.getCModules(): for moduleName in self.getCModules():
indent(file, 0, 'import ' + moduleName + '\n') indent(file, 0, 'import ' + moduleName + '\n')
indent(file, 0, 'import ' + moduleName + 'Downcasts\n')
indent(file, 0, '\n') indent(file, 0, '\n')
indent(file, 0, 'import FFIExternalObject\n') indent(file, 0, 'import FFIExternalObject\n')
@ -637,7 +644,12 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
# that we will call later # that we will call later
if (nesting==0): if (nesting==0):
indent(file, nesting, '# Delay the definition of this class until all the imports are done\n') indent(file, nesting, '# Delay the definition of this class until all the imports are done\n')
indent(file, nesting, '# Make sure we only define this class once\n')
indent(file, nesting, 'classDefined = 0\n')
indent(file, nesting, 'def generateClass_' + self.foreignTypeName + '():\n') indent(file, nesting, 'def generateClass_' + self.foreignTypeName + '():\n')
indent(file, nesting, ' if classDefined: return\n')
indent(file, nesting, ' global classDefined\n')
indent(file, nesting, ' classDefined = 1\n')
# Start the class definition indented a space to account for the function # Start the class definition indented a space to account for the function
indent(file, nesting, ' class ' + self.foreignTypeName) indent(file, nesting, ' class ' + self.foreignTypeName)
else: else:
@ -655,13 +667,22 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
file.write(parentTypeName + '.' + parentTypeName) file.write(parentTypeName + '.' + parentTypeName)
file.write(', ') file.write(', ')
file.write('FFIExternalObject.FFIExternalObject):\n') file.write('FFIExternalObject.FFIExternalObject):\n')
# Store the class C modules for the class so they do not # Store the class C modules for the class so they do not
# get garbage collected before we do # get garbage collected before we do
# TODO: this did not appear to work
indent(file, nesting+1, '__CModules__ = [') indent(file, nesting+1, '__CModules__ = [')
for moduleName in self.getCModules(): for moduleName in self.getCModules():
file.write(moduleName + ',') file.write(moduleName + ',')
file.write(']\n') file.write(']\n')
# Store the downcast function modules so the FFIExternalObject
# can index into them to find the downcast functions
indent(file, nesting+1, '__CModuleDowncasts__ = [')
for moduleName in self.getCModules():
file.write(moduleName + 'Downcasts,')
file.write(']\n')
def outputClassFooter(self, file): def outputClassFooter(self, file):
indent(file, 0, " # When this class gets defined, put it in this module's namespace\n") indent(file, 0, " # When this class gets defined, put it in this module's namespace\n")
@ -744,8 +765,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
if userManagesMemory: if userManagesMemory:
indent(file, nesting, 'returnObject.userManagesMemory = 1\n') indent(file, nesting, 'returnObject.userManagesMemory = 1\n')
if needsDowncast: if needsDowncast:
indent(file, nesting, 'downcastObject = returnObject.setPointer()\n') indent(file, nesting, 'return returnObject.setPointer()\n')
indent(file, nesting, 'return downcastObject\n')
else: else:
indent(file, nesting, 'return returnObject\n') indent(file, nesting, 'return returnObject\n')

View File

@ -109,6 +109,5 @@ else:
# Ok, now we can start generating code # Ok, now we can start generating code
import FFIInterrogateDatabase import FFIInterrogateDatabase
db = FFIInterrogateDatabase.FFIInterrogateDatabase() db = FFIInterrogateDatabase.FFIInterrogateDatabase()
db.updateBindings()
db.generateCode(outputDir, extensionsDir) db.generateCode(outputDir, extensionsDir)

View File

@ -42,12 +42,13 @@ class ShowBase:
self.dataRoot = NodePath(NamedNode('dataRoot'), DataRelation.getClassType()) self.dataRoot = NodePath(NamedNode('dataRoot'), DataRelation.getClassType())
self.dataUnused = NodePath(NamedNode('dataUnused'), DataRelation.getClassType()) self.dataUnused = NodePath(NamedNode('dataUnused'), DataRelation.getClassType())
self.pipe = makeGraphicsPipe() self.pipe = makeGraphicsPipe()
self.win = self.pipe.makeGraphicsWindow(self.renderTop.node(), self.win = makeGraphicsWindow(self.pipe,
self.camera.node(), self.renderTop.node(),
self.dataRoot.node(), self.camera.node(),
self.initialState) self.dataRoot.node(),
self.initialState)
self.render2d = NodePath(self.win.setupPanda2d()) self.render2d = NodePath(setupPanda2d(self.win))
# This is a list of cams associated with the display region's cameras # This is a list of cams associated with the display region's cameras
self.camList = [] self.camList = []
for camera in self.cameraList: for camera in self.cameraList:
@ -105,13 +106,13 @@ class ShowBase:
self.eventMgr.shutdown() self.eventMgr.shutdown()
def toggleBackface(self): def toggleBackface(self):
self.initialState.toggleBackface() toggleBackface(self.initialState)
def toggleTexture(self): def toggleTexture(self):
self.initialState.toggleTexture() toggleTexture(self.initialState)
def toggleWireframe(self): def toggleWireframe(self):
self.initialState.toggleWireframe() toggleWireframe(self.initialState)
def disableMouse(self): def disableMouse(self):
self.drive.reparentTo(self.dataUnused) self.drive.reparentTo(self.dataUnused)

View File

@ -8,20 +8,22 @@ exit = -1
done = 0 done = 0
cont = 1 cont = 1
# Store the global clock
globalClock = ClockObject.getGlobalClock()
def getTimeFrame(): def getTimeFrame():
# WARNING: If you are testing tasks without an igloop, # WARNING: If you are testing tasks without an igloop,
# you must manually tick the clock # you must manually tick the clock
# Ask for the time last frame # Ask for the time last frame
t = ClockObject.getGlobalClock().getTime() t = globalClock.getTime()
# Set the clock to have last frame's time in case we were # Set the clock to have last frame's time in case we were
# Paused at the prompt for a long time # Paused at the prompt for a long time
ClockObject.getGlobalClock().setTime(t) globalClock.setTime(t)
# Get the new frame count # Get the new frame count
f = ClockObject.getGlobalClock().getFrameCount() f = globalClock.getFrameCount()
return t, f return t, f