Skip to content

Commit bae1f25

Browse files
robertgoss-workmartinweismann
authored andcommitted
Initial work to use function tables on a per class basis
1 parent ed32c02 commit bae1f25

File tree

1 file changed

+80
-44
lines changed

1 file changed

+80
-44
lines changed

Source/buildbindingpython.go

Lines changed: 80 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
145145
}
146146
w.Writeln("")
147147

148-
w.Writeln("'''Definition of Function Table")
148+
w.Writeln("'''Definition of Function Tables")
149149
w.Writeln("'''")
150150
w.Writeln("class FunctionTable:")
151151
for j:=0; j<len(componentdefinition.Global.Methods); j++ {
@@ -160,6 +160,15 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
160160
}
161161
}
162162
w.Writeln("")
163+
for i:=0; i<len(componentdefinition.Classes); i++ {
164+
class := componentdefinition.Classes[i]
165+
w.Writeln("class FunctionTable%s:", class.ClassName)
166+
for j:=0; j<len(class.Methods); j++ {
167+
method := class.Methods[j]
168+
w.Writeln(" %s_%s_%s = None", strings.ToLower(NameSpace), strings.ToLower(class.ClassName), strings.ToLower(method.MethodName))
169+
}
170+
w.Writeln("")
171+
}
163172

164173
if (len(componentdefinition.Enums) > 0) {
165174
w.Writeln("'''Definition of Enumerations")
@@ -338,11 +347,8 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
338347
w.Writeln(" ")
339348

340349

341-
w.Writeln(" def checkError(self, instance, errorCode):")
350+
w.Writeln(" def checkError(self, errorCode):")
342351
w.Writeln(" if errorCode != ErrorCodes.SUCCESS.value:")
343-
w.Writeln(" if instance:")
344-
w.Writeln(" if instance._wrapper != self:")
345-
w.Writeln(" raise E%sException(ErrorCodes.INVALIDCAST, 'invalid wrapper call')", NameSpace)
346352
w.Writeln(" message,_ = self.%s(instance)", componentdefinition.Global.ErrorMethod)
347353
w.Writeln(" raise E%sException(errorCode, message)", NameSpace)
348354
w.Writeln(" ")
@@ -391,19 +397,19 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
391397
return nil
392398
}
393399

394-
func writeCDLLFunctionTableMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool) error {
400+
func writeCDLLFunctionTableMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, TableName string, isGlobal bool) error {
395401
exportName := GetCExportName(NameSpace, ClassName, method, isGlobal)
396-
w.Writeln(" self.lib.%s.restype = ctypes.c_int32", exportName)
402+
w.Writeln(" self._functionTable%s.%s.restype = ctypes.c_int32", TableName, exportName)
397403
parameters, err := getMethodCParams(method, NameSpace, ClassName, isGlobal)
398404
if err != nil {
399405
return err
400406
}
401-
w.Writeln(" self.lib.%s.argtypes = [%s]", exportName, parameters)
407+
w.Writeln(" self._functionTable%s.%s.argtypes = [%s]", TableName, exportName, parameters)
402408
w.Writeln(" ")
403409
return nil
404410
}
405411

406-
func writeFunctionTableMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool) error {
412+
func writeFunctionTableMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, TableName string, isGlobal bool) error {
407413
linearMethodName := ""
408414
if (isGlobal) {
409415
linearMethodName = strings.ToLower(NameSpace + "_" + method.MethodName)
@@ -420,7 +426,7 @@ func writeFunctionTableMethod(method ComponentDefinitionMethod, w LanguageWriter
420426
w.Writeln("if err != 0:")
421427
w.Writeln(" raise E%sException(ErrorCodes.COULDNOTLOADLIBRARY, str(err))", NameSpace)
422428
w.Writeln("methodType = ctypes.CFUNCTYPE(ctypes.c_int32, " + params + ")")
423-
w.Writeln("self.lib.%s = methodType(int(methodAddress.value))", linearMethodName)
429+
w.Writeln("self._functionTable%s.%s = methodType(int(methodAddress.value))", TableName, linearMethodName)
424430
w.Writeln("")
425431
return nil
426432
}
@@ -456,7 +462,7 @@ func loadFunctionTableFromMethod(componentdefinition ComponentDefinition, w Lang
456462

457463
for j:=0; j<len(componentdefinition.Global.Methods); j++ {
458464
method := componentdefinition.Global.Methods[j]
459-
err := writeFunctionTableMethod(method, w, componentdefinition.NameSpace, "Wrapper", true)
465+
err := writeFunctionTableMethod(method, w, componentdefinition.NameSpace, "Wrapper", "Wrapper", true)
460466
if err != nil {
461467
return err
462468
}
@@ -465,7 +471,7 @@ func loadFunctionTableFromMethod(componentdefinition ComponentDefinition, w Lang
465471
for i:=0; i<len(componentdefinition.Classes); i++ {
466472
class := componentdefinition.Classes[i]
467473
for j:=0; j<len(class.Methods); j++ {
468-
err := writeFunctionTableMethod(class.Methods[j], w, componentdefinition.NameSpace, class.ClassName, false)
474+
err := writeFunctionTableMethod(class.Methods[j], w, componentdefinition.NameSpace, class.ClassName, "Wrapper", false)
469475
if err != nil {
470476
return err
471477
}
@@ -477,7 +483,7 @@ func loadFunctionTableFromMethod(componentdefinition ComponentDefinition, w Lang
477483

478484
func loadFunctionTable(componentdefinition ComponentDefinition, w LanguageWriter) error {
479485
for j:=0; j<len(componentdefinition.Global.Methods); j++ {
480-
err := writeCDLLFunctionTableMethod(componentdefinition.Global.Methods[j], w, componentdefinition.NameSpace, "Wrapper", true)
486+
err := writeCDLLFunctionTableMethod(componentdefinition.Global.Methods[j], w, componentdefinition.NameSpace, "Wrapper", "Wrapper", true)
481487
if err != nil {
482488
return err
483489
}
@@ -486,7 +492,7 @@ func loadFunctionTable(componentdefinition ComponentDefinition, w LanguageWriter
486492
for i:=0; i<len(componentdefinition.Classes); i++ {
487493
class := componentdefinition.Classes[i]
488494
for j:=0; j<len(class.Methods); j++ {
489-
err := writeCDLLFunctionTableMethod(class.Methods[j], w, componentdefinition.NameSpace, class.ClassName, false)
495+
err := writeCDLLFunctionTableMethod(class.Methods[j], w, componentdefinition.NameSpace, class.ClassName, "Wrapper", false)
490496
if err != nil {
491497
return err
492498
}
@@ -716,7 +722,6 @@ func generateCTypesParameter(param ComponentDefinitionParam, className string, m
716722
return cParams, nil;
717723
}
718724

719-
720725
func writePythonClass(component ComponentDefinition, class ComponentDefinitionClass, w LanguageWriter, NameSpace string) error {
721726
pythonBaseClassName := fmt.Sprintf("%s", component.Global.BaseClassName)
722727

@@ -730,21 +735,37 @@ func writePythonClass(component ComponentDefinition, class ComponentDefinitionCl
730735
} else {
731736
parentClass = pythonBaseClassName
732737
}
733-
w.Writeln("class %s(%s):", class.ClassName, parentClass)
734-
w.Writeln(" def __init__(self, handle, wrapper):")
735-
w.Writeln(" %s.__init__(self, handle, wrapper)", parentClass)
738+
}
736739

740+
if (!component.isBaseClass(class)) {
741+
w.Writeln("class %s(%s):", class.ClassName, parentClass)
742+
w.Writeln(" _mapMethodToFunctionTable%s={}", class.ClassName)
743+
w.Writeln(" ")
744+
w.Writeln(" def __init__(self, handle):")
745+
w.Writeln(" %s.__init__(self, handle)", parentClass)
737746
} else {
738747
w.Writeln("class %s:", class.ClassName)
739-
w.Writeln(" def __init__(self, handle, wrapper):")
740-
w.Writeln(" if not handle or not wrapper:")
741-
w.Writeln(" raise E%sException(ErrorCodes.INVALIDPARAM)", NameSpace)
748+
w.Writeln(" _mapMethodToFunctionTable%s={}", class.ClassName)
749+
w.Writeln(" ")
750+
w.Writeln(" def __init__(self, handle):")
751+
w.Writeln(" if not handle:")
752+
w.Writeln(" raise E%sException(ErrorCodes.INVALIDPARAM)", NameSpace)
742753
w.Writeln(" self._handle = handle")
743-
w.Writeln(" self._wrapper = wrapper")
744-
w.Writeln(" self._wrapper.%s(self)", component.Global.AcquireMethod)
754+
}
755+
756+
w.Writeln(" self._functionTable%s = %s._lookupFunctionTable%s(handle)", class.ClassName, class.ClassName, class.ClassName)
757+
758+
if (component.isBaseClass(class)) {
759+
w.Writeln(" self.%s(self)", component.Global.AcquireMethod)
745760
w.Writeln(" ")
746761
w.Writeln(" def __del__(self):")
747-
w.Writeln(" self._wrapper.%s(self)", component.Global.ReleaseMethod)
762+
w.Writeln(" self.%s(self)", component.Global.ReleaseMethod)
763+
}
764+
w.Writeln("")
765+
writeFunctionTableLookup(class, w)
766+
err := writeFunctionTableLoadFromMethod(class, w, NameSpace)
767+
if (err != nil) {
768+
return err
748769
}
749770

750771
for i:=0; i<len(class.Methods); i++ {
@@ -756,20 +777,44 @@ func writePythonClass(component ComponentDefinition, class ComponentDefinitionCl
756777
return nil
757778
}
758779

780+
func writeFunctionTableLookup(class ComponentDefinitionClass, w LanguageWriter) {
781+
w.Writeln(" @staticmethod")
782+
w.Writeln(" def _lookupFunctionTable%s(cls, handle):", class.ClassName)
783+
w.Writeln(" method = handle.symbolLookupMethod")
784+
w.Writeln(" if method in cls._mapMethodToFunctionTable%s:", class.ClassName)
785+
w.Writeln(" return cls._mapMethodToFunctionTable%s[method]", class.ClassName)
786+
w.Writeln(" table = self._loadFunctionTable%sFromMethod(method)", class.ClassName)
787+
w.Writeln(" cls._mapMethodToFunctionTable%s[method] = table", class.ClassName)
788+
w.Writeln(" return table")
789+
w.Writeln("")
790+
}
791+
792+
func writeFunctionTableLoadFromMethod(class ComponentDefinitionClass, w LanguageWriter, NameSpace string) error {
793+
w.Writeln(" def _loadFunctionTable%s(self, handle):", class.ClassName)
794+
w.Writeln(" try:")
795+
w.Writeln(" symbolLookupMethod = handle.symbolLookupMethod")
796+
w.Writeln(" methodAddress = ctypes.c_void_p()")
797+
w.Writeln(" ")
798+
w.AddIndentationLevel(3)
799+
for j:=0; j<len(class.Methods); j++ {
800+
err := writeFunctionTableMethod(class.Methods[j], w, NameSpace, class.ClassName, class.ClassName, false)
801+
if err != nil {
802+
return err
803+
}
804+
}
805+
w.Writeln(" except AttributeError as ae:")
806+
w.Writeln(" raise EDMKCalcException(ErrorCodes.COULDNOTFINDLIBRARYEXPORT, ae.args[0])")
807+
w.Writeln("")
808+
return nil
809+
}
810+
759811
func writeMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, implementationLines []string, isGlobal bool) error {
760812
preCallLines := []string{}
761813
checkCallLines := []string{}
762814
postCallLines := []string{}
763815

764816
retVals := ""
765817
pythonInParams := ""
766-
767-
wrapperReference := "self"
768-
selfReference := "None"
769-
if (!isGlobal) {
770-
wrapperReference = "self._wrapper"
771-
selfReference = "self"
772-
}
773818
cArguments := ""
774819
if (!isGlobal) {
775820
cArguments = "self._handle"
@@ -805,20 +850,11 @@ func writeMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace s
805850
cArguments = cArguments + newArgument
806851
cCheckArguments = cCheckArguments + newArgument
807852

808-
theWrapperReference := wrapperReference
809853
subNameSpace, paramClassName, _ := decomposeParamClassName(param.ParamClass)
810-
if len(subNameSpace) > 0 {
811-
theWrapperReference = theWrapperReference + "._" + subNameSpace + "Wrapper"
812-
if subNameSpace != NameSpace {
813-
subNameSpace = subNameSpace + ".";
814-
} else {
815-
subNameSpace = "";
816-
}
817-
}
818854
postCallLines = append(postCallLines, fmt.Sprintf("if %sHandle:", param.ParamName))
819855
postCallLines = append(postCallLines,
820-
fmt.Sprintf(" %sObject = %s%s(%sHandle, %s)",
821-
param.ParamName, subNameSpace, paramClassName, param.ParamName, theWrapperReference))
856+
fmt.Sprintf(" %sObject = %s%s(%sHandle)",
857+
param.ParamName, subNameSpace, paramClassName, param.ParamName))
822858
postCallLines = append(postCallLines, fmt.Sprintf("else:"))
823859
if (param.ParamType == "optionalclass") {
824860
postCallLines = append(postCallLines, fmt.Sprintf(" %sObject = None", param.ParamName))
@@ -979,10 +1015,10 @@ func writeMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace s
9791015
w.Writeln(" def %s(self%s):", method.MethodName, pythonInParams)
9801016
w.Writelns(" ", preCallLines)
9811017
if (doCheckCall) {
982-
w.Writeln(" %s.checkError(%s, %s.lib.%s(%s))", wrapperReference, selfReference, wrapperReference, exportName, cCheckArguments)
1018+
w.Writeln(" self.checkError(self._functionTable%s.%s(%s))", ClassName, exportName, cCheckArguments)
9831019
w.Writelns(" ", checkCallLines)
9841020
}
985-
w.Writeln(" %s.checkError(%s, %s.lib.%s(%s))", wrapperReference, selfReference, wrapperReference, exportName, cArguments)
1021+
w.Writeln(" self.checkError(self._functionTable%s.%s(%s))", ClassName, exportName, cArguments)
9861022
w.Writelns(" ", postCallLines)
9871023
w.Writeln(" ")
9881024

0 commit comments

Comments
 (0)