mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 15:53:55 -04:00
*** empty log message ***
This commit is contained in:
parent
d52b03d69a
commit
237a3e50a2
@ -5,6 +5,7 @@ class FFIEnvironment:
|
|||||||
self.types = {}
|
self.types = {}
|
||||||
self.globalFunctions = []
|
self.globalFunctions = []
|
||||||
self.globalValues = []
|
self.globalValues = []
|
||||||
|
self.manifests = []
|
||||||
|
|
||||||
def addType(self, typeDescriptor, name):
|
def addType(self, typeDescriptor, name):
|
||||||
if self.types.has_key(name):
|
if self.types.has_key(name):
|
||||||
@ -21,3 +22,5 @@ class FFIEnvironment:
|
|||||||
self.globalFunctions.append(typeDescriptor)
|
self.globalFunctions.append(typeDescriptor)
|
||||||
def addGlobalValue(self, typeDescriptor):
|
def addGlobalValue(self, typeDescriptor):
|
||||||
self.globalValues.append(typeDescriptor)
|
self.globalValues.append(typeDescriptor)
|
||||||
|
def addManifest(self, typeDescriptor):
|
||||||
|
self.manifests.append(typeDescriptor)
|
||||||
|
@ -44,6 +44,9 @@ def outputGlobalFileImports(file, methodList):
|
|||||||
# Print the standard header
|
# Print the standard header
|
||||||
file.write(FFIConstants.generatedHeader)
|
file.write(FFIConstants.generatedHeader)
|
||||||
|
|
||||||
|
# Import Python's builtin types
|
||||||
|
file.write('import types\n')
|
||||||
|
|
||||||
# Import the C modules
|
# Import the C modules
|
||||||
for CModuleName in FFIConstants.CodeModuleNameList:
|
for CModuleName in FFIConstants.CodeModuleNameList:
|
||||||
file.write('import ' + CModuleName + '\n')
|
file.write('import ' + CModuleName + '\n')
|
||||||
@ -370,7 +373,10 @@ class FFIInterrogateDatabase:
|
|||||||
# Prepend lib to the module name it reports because that will be the name of
|
# 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
|
# the Python module we import. This is apparently stems from a makefile
|
||||||
# discrepency in the way we build the libraries
|
# discrepency in the way we build the libraries
|
||||||
moduleName = 'lib' + interrogate_function_module_name(functionIndex)
|
if interrogate_function_has_module_name(functionIndex):
|
||||||
|
moduleName = 'lib' + interrogate_function_module_name(functionIndex)
|
||||||
|
else:
|
||||||
|
moduleName = None
|
||||||
typeIndex = functionIndex
|
typeIndex = functionIndex
|
||||||
|
|
||||||
# Look at the Python wrappers for this function
|
# Look at the Python wrappers for this function
|
||||||
@ -497,6 +503,8 @@ class FFIInterrogateDatabase:
|
|||||||
# funcSpec.name = FFIRename.methodNameFromCppName(
|
# funcSpec.name = FFIRename.methodNameFromCppName(
|
||||||
# interrogate_function_name(funcIndex))
|
# interrogate_function_name(funcIndex))
|
||||||
funcSpec.typeDescriptor = typeDesc
|
funcSpec.typeDescriptor = typeDesc
|
||||||
|
# Flag this function as being a constructor
|
||||||
|
funcSpec.constructor = 1
|
||||||
funcSpec.index = funcIndex
|
funcSpec.index = funcIndex
|
||||||
funcSpecs.append(funcSpec)
|
funcSpecs.append(funcSpec)
|
||||||
return funcSpecs
|
return funcSpecs
|
||||||
@ -528,7 +536,9 @@ class FFIInterrogateDatabase:
|
|||||||
def constructGlobal(self, globalIndex):
|
def constructGlobal(self, globalIndex):
|
||||||
# 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
|
||||||
# descriptor = self.typeIndexMap[interrogate_element_type(globalIndex)]
|
# typeIndex = interrogate_element_type(globalIndex)
|
||||||
|
# descriptor = self.constructDescriptor(typeIndex)
|
||||||
|
|
||||||
if interrogate_element_has_getter(globalIndex):
|
if interrogate_element_has_getter(globalIndex):
|
||||||
getterIndex = interrogate_element_getter(globalIndex)
|
getterIndex = interrogate_element_getter(globalIndex)
|
||||||
getter = self.constructGlobalFunction(getterIndex)
|
getter = self.constructGlobalFunction(getterIndex)
|
||||||
@ -602,6 +612,46 @@ class FFIInterrogateDatabase:
|
|||||||
newGlob = self.constructGlobal(globalIndex)
|
newGlob = self.constructGlobal(globalIndex)
|
||||||
self.environment.addGlobalValue(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):
|
def generateCode(self, codeDir, extensionsDir):
|
||||||
FFIConstants.notify.info( 'Generating static class...')
|
FFIConstants.notify.info( 'Generating static class...')
|
||||||
generateStaticClass(codeDir)
|
generateStaticClass(codeDir)
|
||||||
@ -627,6 +677,7 @@ class FFIInterrogateDatabase:
|
|||||||
# 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)
|
||||||
|
|
||||||
|
FFIConstants.notify.info( 'Generating global value code...')
|
||||||
for type in self.environment.globalValues:
|
for type in self.environment.globalValues:
|
||||||
type.generateGlobalCode(globalFile)
|
type.generateGlobalCode(globalFile)
|
||||||
|
|
||||||
@ -634,13 +685,17 @@ class FFIInterrogateDatabase:
|
|||||||
for type in self.environment.globalFunctions:
|
for type in self.environment.globalFunctions:
|
||||||
type.generateGlobalCode(globalFile)
|
type.generateGlobalCode(globalFile)
|
||||||
|
|
||||||
|
FFIConstants.notify.info( 'Generating manifest code...')
|
||||||
|
for type in self.environment.manifests:
|
||||||
|
type.generateGlobalCode(globalFile)
|
||||||
|
|
||||||
globalFile.close()
|
globalFile.close()
|
||||||
|
|
||||||
FFIConstants.notify.info( 'Generating import code...')
|
FFIConstants.notify.info( 'Generating import code...')
|
||||||
importFile = constructImportFile(codeDir)
|
importFile = constructImportFile(codeDir)
|
||||||
outputImportFileImports(importFile, self.environment.types.values())
|
outputImportFileImports(importFile, self.environment.types.values())
|
||||||
|
|
||||||
|
FFIConstants.notify.info( 'Compiling code...')
|
||||||
compileall.compile_dir(codeDir)
|
compileall.compile_dir(codeDir)
|
||||||
|
|
||||||
|
|
||||||
@ -652,4 +707,9 @@ class FFIInterrogateDatabase:
|
|||||||
self.addGlobalValues()
|
self.addGlobalValues()
|
||||||
FFIConstants.notify.info( 'Adding global functions...')
|
FFIConstants.notify.info( 'Adding global functions...')
|
||||||
self.addGlobalFunctions()
|
self.addGlobalFunctions()
|
||||||
|
FFIConstants.notify.info( 'Adding manifests symbols...')
|
||||||
|
self.addManifestSymbols()
|
||||||
|
FFIConstants.notify.info( 'Adding environment types...')
|
||||||
self.addEnvironmentTypes()
|
self.addEnvironmentTypes()
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,11 +3,13 @@ from PythonUtil import *
|
|||||||
from types import *
|
from types import *
|
||||||
import string
|
import string
|
||||||
import FFIConstants
|
import FFIConstants
|
||||||
|
import FFISpecs
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Things that are not supported:
|
Things that are not supported:
|
||||||
- Overloading a function based on an enum being differentiated from an int
|
- Overloading a function based on an enum being differentiated from an int
|
||||||
- Type names from C++ cannot begin with __enum__
|
- Type names from C++ cannot have __enum__ in their name
|
||||||
|
- Overloading static and non-static methods with the same name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
AT_not_atomic = 0
|
AT_not_atomic = 0
|
||||||
@ -52,10 +54,16 @@ def getTypeName(classTypeDesc, typeDesc):
|
|||||||
# Convert the void type to None type... I guess...
|
# Convert the void type to None type... I guess...
|
||||||
# So far we do not have any code that uses this
|
# So far we do not have any code that uses this
|
||||||
return 'types.NoneType'
|
return 'types.NoneType'
|
||||||
|
|
||||||
|
else:
|
||||||
|
FFIConstants.notify.error("Unknown atomicType: " + typeDesc.atomicType)
|
||||||
|
|
||||||
# If the type is an enum, we really want to treat it like an int
|
# If the type is an enum, we really want to treat it like an int
|
||||||
# To handle this, the type will have __enum__ prepended to the name
|
# To handle this, the type will have __enum__ in the name
|
||||||
elif (typeName[0:8] == '__enum__'):
|
# Usually it will start the typeName, but some typeNames have the
|
||||||
|
# surrounding class as part of their name
|
||||||
|
# like BoundedObject.__enum__BoundingVolumeType
|
||||||
|
elif (typeName.find('__enum__') >= 0):
|
||||||
return 'types.IntType'
|
return 'types.IntType'
|
||||||
|
|
||||||
# If it was not atomic or enum, it must be a class which is a
|
# If it was not atomic or enum, it must be a class which is a
|
||||||
@ -146,15 +154,44 @@ class FFIMethodArgumentTreeCollection:
|
|||||||
self.methodDict = {}
|
self.methodDict = {}
|
||||||
self.treeDict = {}
|
self.treeDict = {}
|
||||||
|
|
||||||
def outputOverloadedMethodHeader(self, file):
|
def outputOverloadedMethodHeader(self, file, nesting):
|
||||||
indent(file, 1, 'def ' + self.methodSpecList[0].name
|
# If one is static, we assume they all are.
|
||||||
+ '(self, *_args):\n')
|
# The current system does not support overloading static and non-static
|
||||||
indent(file, 2, 'numArgs = len(_args)\n')
|
# methods with the same name
|
||||||
|
# Constructors are not treated as static. They are special because
|
||||||
|
# they are not really constructors, they are instance methods that fill
|
||||||
|
# in the this pointer.
|
||||||
|
if (self.methodSpecList[0].isStatic() and
|
||||||
|
(not self.methodSpecList[0].isConstructor())):
|
||||||
|
indent(file, nesting+1, 'def ' +
|
||||||
|
self.methodSpecList[0].name + '(*_args):\n')
|
||||||
|
else:
|
||||||
|
indent(file, nesting+1, 'def ' +
|
||||||
|
self.methodSpecList[0].name + '(self, *_args):\n')
|
||||||
|
indent(file, nesting+2, 'numArgs = len(_args)\n')
|
||||||
|
|
||||||
def outputOverloadedMethodFooter(self, file):
|
def outputOverloadedMethodFooter(self, file, nesting):
|
||||||
# If the overloaded function got all the way through the if statements
|
# If the overloaded function got all the way through the if statements
|
||||||
# it must have had the wrong number or type of arguments
|
# it must have had the wrong number or type of arguments
|
||||||
indent(file, 2, "raise TypeError, 'Invalid arguments'\n\n")
|
indent(file, nesting+2, "raise TypeError, 'Invalid arguments'\n")
|
||||||
|
|
||||||
|
# If this is a static method, we need to output a static version
|
||||||
|
# If one is static, we assume they all are.
|
||||||
|
# The current system does not support overloading static and non-static
|
||||||
|
# methods with the same name
|
||||||
|
# Constructors are not treated as static. They are special because
|
||||||
|
# they are not really constructors, they are instance methods that fill
|
||||||
|
# in the this pointer.
|
||||||
|
|
||||||
|
if (self.methodSpecList[0].isStatic() and
|
||||||
|
(not self.methodSpecList[0].isConstructor())):
|
||||||
|
self.outputOverloadedStaticFooter(file, nesting)
|
||||||
|
indent(file, nesting+1, '\n')
|
||||||
|
|
||||||
|
def outputOverloadedStaticFooter(self, file, nesting):
|
||||||
|
indent(file, nesting+1, self.methodSpecList[0].name + ' = '
|
||||||
|
+ FFIConstants.staticModuleName + '.' + FFIConstants.staticModuleName
|
||||||
|
+ '(' + self.methodSpecList[0].name + ')\n')
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
for method in self.methodSpecList:
|
for method in self.methodSpecList:
|
||||||
@ -169,16 +206,16 @@ class FFIMethodArgumentTreeCollection:
|
|||||||
|
|
||||||
def generateCode(self, file, nesting):
|
def generateCode(self, file, nesting):
|
||||||
self.setup()
|
self.setup()
|
||||||
self.outputOverloadedMethodHeader(file)
|
self.outputOverloadedMethodHeader(file, nesting)
|
||||||
numArgsKeys = self.treeDict.keys()
|
numArgsKeys = self.treeDict.keys()
|
||||||
numArgsKeys.sort()
|
numArgsKeys.sort()
|
||||||
for numArgs in numArgsKeys:
|
for numArgs in numArgsKeys:
|
||||||
trees = self.treeDict[numArgs]
|
trees = self.treeDict[numArgs]
|
||||||
for tree in trees:
|
for tree in trees:
|
||||||
indent(file, 2, 'if (numArgs == ' + `numArgs` + '):\n')
|
indent(file, nesting+2, 'if (numArgs == ' + `numArgs` + '):\n')
|
||||||
tree.setup()
|
tree.setup()
|
||||||
tree.traverse(file)
|
tree.traverse(file, nesting+1)
|
||||||
self.outputOverloadedMethodFooter(file)
|
self.outputOverloadedMethodFooter(file, nesting)
|
||||||
|
|
||||||
class FFIMethodArgumentTree:
|
class FFIMethodArgumentTree:
|
||||||
"""
|
"""
|
||||||
@ -241,7 +278,7 @@ class FFIMethodArgumentTree:
|
|||||||
# Output the function
|
# Output the function
|
||||||
methodSpec = self.tree[0][1]
|
methodSpec = self.tree[0][1]
|
||||||
indent(file, level+2, 'return ')
|
indent(file, level+2, 'return ')
|
||||||
methodSpec.outputOverloadedCall(file, 0)
|
methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0)
|
||||||
else:
|
else:
|
||||||
typeName = getTypeName(self.classTypeDesc, typeDesc)
|
typeName = getTypeName(self.classTypeDesc, typeDesc)
|
||||||
indent(file, level+2, 'if (isinstance(_args[' + `level-1` + '], '
|
indent(file, level+2, 'if (isinstance(_args[' + `level-1` + '], '
|
||||||
@ -260,7 +297,7 @@ class FFIMethodArgumentTree:
|
|||||||
methodSpec = self.tree[typeDesc][1]
|
methodSpec = self.tree[typeDesc][1]
|
||||||
indent(file, level+3, 'return ')
|
indent(file, level+3, 'return ')
|
||||||
numArgs = level
|
numArgs = level
|
||||||
methodSpec.outputOverloadedCall(file, numArgs)
|
methodSpec.outputOverloadedCall(file, self.classTypeDesc, numArgs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,18 @@ class FunctionSpecification:
|
|||||||
self.typeDescriptor = None
|
self.typeDescriptor = None
|
||||||
self.index = 0
|
self.index = 0
|
||||||
self.overloaded = 0
|
self.overloaded = 0
|
||||||
|
# Is this function a constructor
|
||||||
|
self.constructor = 0
|
||||||
|
|
||||||
|
def isConstructor(self):
|
||||||
|
return self.constructor
|
||||||
|
|
||||||
|
def isStatic(self):
|
||||||
|
for arg in self.typeDescriptor.argumentTypes:
|
||||||
|
if arg.isThis:
|
||||||
|
return 0
|
||||||
|
# No args were this pointers, must be static
|
||||||
|
return 1
|
||||||
|
|
||||||
def outputTypeChecking(self, methodClass, args, file, nesting):
|
def outputTypeChecking(self, methodClass, args, file, nesting):
|
||||||
"""
|
"""
|
||||||
@ -73,13 +85,26 @@ class FunctionSpecification:
|
|||||||
else:
|
else:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def outputOverloadedCall(self, file, numArgs):
|
def outputOverloadedCall(self, file, classTypeDesc, numArgs):
|
||||||
"""
|
"""
|
||||||
Write the function call to call this overloaded method
|
Write the function call to call this overloaded method
|
||||||
For example:
|
For example:
|
||||||
self.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2])
|
self.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2])
|
||||||
|
If it is a class (static) method, call the class method
|
||||||
|
Class.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2])
|
||||||
|
|
||||||
|
Constructors are not treated as static. They are special because
|
||||||
|
they are not really constructors, they are instance methods that fill
|
||||||
|
in the this pointer.
|
||||||
|
|
||||||
|
These do not get indented because they are not the beginning of the line
|
||||||
|
|
||||||
"""
|
"""
|
||||||
indent(file, 0, 'self.' + self.getFinalName() + '(')
|
if (self.isStatic() and not self.isConstructor()):
|
||||||
|
indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(')
|
||||||
|
else:
|
||||||
|
indent(file, 0, 'self.' + self.getFinalName() + '(')
|
||||||
|
|
||||||
for i in range(numArgs):
|
for i in range(numArgs):
|
||||||
file.write('_args[' + `i` + ']')
|
file.write('_args[' + `i` + ']')
|
||||||
if (i != (numArgs - 1)):
|
if (i != (numArgs - 1)):
|
||||||
@ -230,11 +255,6 @@ class GlobalFunctionSpecification(FunctionSpecification):
|
|||||||
class MethodSpecification(FunctionSpecification):
|
class MethodSpecification(FunctionSpecification):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
FunctionSpecification.__init__(self)
|
FunctionSpecification.__init__(self)
|
||||||
def isStatic(self):
|
|
||||||
for arg in self.typeDescriptor.argumentTypes:
|
|
||||||
if arg.isThis:
|
|
||||||
return 0
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def generateConstructorCode(self, methodClass, file, nesting):
|
def generateConstructorCode(self, methodClass, file, nesting):
|
||||||
self.outputConstructorHeader(methodClass, file, nesting)
|
self.outputConstructorHeader(methodClass, file, nesting)
|
||||||
@ -484,6 +504,47 @@ class GlobalValueSpecification:
|
|||||||
self.setter.generateGlobalCode(file)
|
self.setter.generateGlobalCode(file)
|
||||||
indent(file, 0, '\n')
|
indent(file, 0, '\n')
|
||||||
|
|
||||||
|
|
||||||
|
# Manifest symbols
|
||||||
|
class ManifestSpecification:
|
||||||
|
def __init__(self):
|
||||||
|
self.name = ''
|
||||||
|
|
||||||
|
# We are not currently using the type descriptor
|
||||||
|
self.typeDescriptor = None
|
||||||
|
|
||||||
|
# To be filled in with a GlobalFunctionSpecification
|
||||||
|
# if this manifest has one
|
||||||
|
self.getter = None
|
||||||
|
|
||||||
|
# Manifests that have int values have their int value defined
|
||||||
|
# instead of having to call a getter (because there are so many of them)
|
||||||
|
self.intValue = None
|
||||||
|
|
||||||
|
# The string definition of this manifest
|
||||||
|
self.definition = None
|
||||||
|
|
||||||
|
def generateGlobalCode(self, file):
|
||||||
|
# Note, if the manifest has no value and no getter we do not output anything
|
||||||
|
# even though they may be defined in the C++ sense. Without any values
|
||||||
|
# they are pretty useless in Python
|
||||||
|
|
||||||
|
# If it has an int value, just output that instead of bothering
|
||||||
|
# with a getter
|
||||||
|
if (self.intValue != None):
|
||||||
|
indent(file, 0, '# Manifest: ' + self.name + '\n')
|
||||||
|
indent(file, 0, (self.name + ' = ' + `self.intValue` + '\n'))
|
||||||
|
indent(file, 0, '\n')
|
||||||
|
|
||||||
|
elif self.definition:
|
||||||
|
indent(file, 0, ('# Manifest: ' + self.name + ' definition: ' +
|
||||||
|
self.definition + '\n'))
|
||||||
|
# Out put the getter
|
||||||
|
if self.getter:
|
||||||
|
self.getter.generateGlobalCode(file)
|
||||||
|
indent(file, 0, '\n')
|
||||||
|
|
||||||
|
|
||||||
class MethodArgumentSpecification:
|
class MethodArgumentSpecification:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.name = ''
|
self.name = ''
|
||||||
|
Loading…
x
Reference in New Issue
Block a user