diff --git a/README.md b/README.md index bc4ce645..f79a5a8e 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ ACT supports generation of bindings or implementation stubs for C++, C, Pascal, | C Dynamic | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | + | - | | Pascal | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | + | + | | Python3 | ![](Documentation/images/Tick.png) complete (but not very pythonic) | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | + | + | -| Golang | ![](Documentation/images/O.png) partial support | Win, Linux, MacOS | in,return | in,out,return | ? | ? | ? | ? | ? | - | - | - | +| Golang | ![](Documentation/images/O.png) partial support | Win, Linux, MacOS | in,return | in,out,return | ? | ? | in,out,return | in,out | in,out | - | - | - | | NodeJS | ![](Documentation/images/O.png) partial support | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | ? | ? | - | + | - | | C# | ![](Documentation/images/O.png) experimental | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | - | - | - | + | - | | Java | ![](Documentation/images/Tick.png) experimental | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | + | + | diff --git a/Source/buildbindinggo.go b/Source/buildbindinggo.go index 5dabe5fe..3479f51c 100644 --- a/Source/buildbindinggo.go +++ b/Source/buildbindinggo.go @@ -145,7 +145,6 @@ func buildGoExample(component ComponentDefinition, w LanguageWriter, outputFolde w.Writeln("") } - func buildGoEnums(component ComponentDefinition, w LanguageWriter) { if len(component.Enums) <= 0 { return @@ -166,7 +165,7 @@ func buildGoEnums(component ComponentDefinition, w LanguageWriter) { for j := 0; j < len(enum.Options); j++ { option := enum.Options[j] - w.Writeln(" e%s_%s = %d", enum.Name, option.Name, option.Value) + w.Writeln(" %s_%s = %d", enum.Name, option.Name, option.Value) } w.Writeln(")") w.Writeln("") @@ -174,7 +173,7 @@ func buildGoEnums(component ComponentDefinition, w LanguageWriter) { w.Writeln("") } -func buildGoStructs(component ComponentDefinition, w LanguageWriter) (error) { +func buildGoStructs(component ComponentDefinition, w LanguageWriter) error { if len(component.Structs) <= 0 { return nil } @@ -278,7 +277,7 @@ func buildGoImplementation(component ComponentDefinition, implw LanguageWriter) implw.Writeln("") } -func buildGoImplementationHandle(component ComponentDefinition, implw LanguageWriter) { +func buildGoImplementationHandle(component ComponentDefinition, implw LanguageWriter) { NameSpace := component.NameSpace implw.Writeln("type %sImplementationHandle interface {", NameSpace) implw.Writeln(" %sHandle", NameSpace) @@ -452,6 +451,12 @@ func buildGoCallFunction(component ComponentDefinition, implw LanguageWriter) { implw.Writeln(" case 10: ret, _, _ = syscall.Syscall12(funcptr, 10, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), 0, 0)") implw.Writeln(" case 11: ret, _, _ = syscall.Syscall12(funcptr, 11, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), 0)") implw.Writeln(" case 12: ret, _, _ = syscall.Syscall12(funcptr, 12, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]))") + implw.Writeln(" case 13: ret, _, _ = syscall.Syscall15(funcptr, 13, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), 0, 0)") + implw.Writeln(" case 14: ret, _, _ = syscall.Syscall15(funcptr, 14, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), uintptr(parameters[13]), 0)") + implw.Writeln(" case 15: ret, _, _ = syscall.Syscall15(funcptr, 15, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), uintptr(parameters[13]), uintptr(parameters[14]))") + implw.Writeln(" case 16: ret, _, _ = syscall.Syscall18(funcptr, 16, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), uintptr(parameters[13]), uintptr(parameters[14]), uintptr(parameters[15]), 0, 0)") + implw.Writeln(" case 17: ret, _, _ = syscall.Syscall18(funcptr, 17, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), uintptr(parameters[13]), uintptr(parameters[14]), uintptr(parameters[15]), uintptr(parameters[16]), 0)") + implw.Writeln(" case 18: ret, _, _ = syscall.Syscall18(funcptr, 18, uintptr(parameters[0]), uintptr(parameters[1]), uintptr(parameters[2]), uintptr(parameters[3]), uintptr(parameters[4]), uintptr(parameters[5]), uintptr(parameters[6]), uintptr(parameters[7]), uintptr(parameters[8]), uintptr(parameters[9]), uintptr(parameters[10]), uintptr(parameters[11]), uintptr(parameters[12]), uintptr(parameters[13]), uintptr(parameters[14]), uintptr(parameters[15]), uintptr(parameters[16]), uintptr(parameters[17]))") implw.Writeln(" default: ") implw.Writeln(" return errors.New(\"Invalid DLL function parameter count!\");") implw.Writeln(" }") @@ -465,26 +470,25 @@ func buildGoCallFunction(component ComponentDefinition, implw LanguageWriter) { implw.Writeln("") } - -func buildGoClass(component ComponentDefinition, class ComponentDefinitionClass, w LanguageWriter, implw LanguageWriter, NameSpace string, classdefinitions* []string) (error) { +func buildGoClass(component ComponentDefinition, class ComponentDefinitionClass, w LanguageWriter, implw LanguageWriter, NameSpace string, classdefinitions *[]string) error { *classdefinitions = append(*classdefinitions, fmt.Sprintf("")) *classdefinitions = append(*classdefinitions, fmt.Sprintf("/*************************************************************************************************************************")) *classdefinitions = append(*classdefinitions, fmt.Sprintf("Class definition %s%s", NameSpace, class.ClassName)) *classdefinitions = append(*classdefinitions, fmt.Sprintf("**************************************************************************************************************************/")) *classdefinitions = append(*classdefinitions, fmt.Sprintf("")) - *classdefinitions = append(*classdefinitions, fmt.Sprintf("type %s%s struct {", NameSpace, class.ClassName)) + *classdefinitions = append(*classdefinitions, fmt.Sprintf("type %s%s struct {", NameSpace, class.ClassName)) - if (component.Global.BaseClassName == class.ClassName) { - *classdefinitions = append(*classdefinitions, fmt.Sprintf(" Interface %sGoInterface", NameSpace)) + if component.Global.BaseClassName == class.ClassName { + *classdefinitions = append(*classdefinitions, fmt.Sprintf(" Interface %sGoInterface", NameSpace)) *classdefinitions = append(*classdefinitions, fmt.Sprintf(" Handle %sHandle", NameSpace)) } else { - if len(class.ParentClass)>0 { + if len(class.ParentClass) > 0 { *classdefinitions = append(*classdefinitions, fmt.Sprintf(" %s%s", NameSpace, class.ParentClass)) } else { *classdefinitions = append(*classdefinitions, fmt.Sprintf(" %s%s", NameSpace, component.Global.BaseClassName)) } } - + *classdefinitions = append(*classdefinitions, fmt.Sprintf("}")) *classdefinitions = append(*classdefinitions, fmt.Sprintf("")) *classdefinitions = append(*classdefinitions, fmt.Sprintf("func (instance *%s%s) Close() (error) {", NameSpace, class.ClassName)) @@ -514,7 +518,7 @@ func buildGoWrapper(component ComponentDefinition, w LanguageWriter, implw Langu buildGoEnums(component, w) err := buildGoStructs(component, w) - if (err != nil) { + if err != nil { return err } buildGoInterfaces(component, w) @@ -540,7 +544,7 @@ func buildGoWrapper(component ComponentDefinition, w LanguageWriter, implw Langu buildGoHelperFunctions(implw) buildGoErrorHandling(component, implw) - + implw.Writeln("") implw.Writeln("func (implementation *%sImplementation) GetWrapperHandle(handle %sHandle) (%sImplementationHandle, error) {", NameSpace, NameSpace, NameSpace) implw.Writeln(" implementation_handle, ok := handle.(%sImplementationHandle)", NameSpace) @@ -661,18 +665,30 @@ func getGoBasicType(paramType string) (string, error) { func paramFunction(paramType string, paramPass string) (string, error) { paramFunctionStr := "" switch paramType { - case "uint8": paramFunctionStr = "UInt8" - case "uint16": paramFunctionStr = "UInt16" - case "uint32": paramFunctionStr = "UInt32" - case "uint64": paramFunctionStr = "UInt64" - case "int8": paramFunctionStr = "Int8" - case "int16": paramFunctionStr = "Int16" - case "int32": paramFunctionStr = "Int32" - case "int64": paramFunctionStr = "Int64" - case "bool": paramFunctionStr = "bool" - case "single": paramFunctionStr = "Float32" - case "double": paramFunctionStr = "Float64" - case "pointer": paramFunctionStr = "UInt64" + case "uint8": + paramFunctionStr = "UInt8" + case "uint16": + paramFunctionStr = "UInt16" + case "uint32": + paramFunctionStr = "UInt32" + case "uint64": + paramFunctionStr = "UInt64" + case "int8": + paramFunctionStr = "Int8" + case "int16": + paramFunctionStr = "Int16" + case "int32": + paramFunctionStr = "Int32" + case "int64": + paramFunctionStr = "Int64" + case "bool": + paramFunctionStr = "bool" + case "single": + paramFunctionStr = "Float32" + case "double": + paramFunctionStr = "Float64" + case "pointer": + paramFunctionStr = "UInt64" default: return "", errors.New("Invalid basic type: " + paramType) } @@ -682,19 +698,19 @@ func paramFunction(paramType string, paramPass string) (string, error) { } else { paramFunctionStr += "OutValue" } - return paramFunctionStr , nil + return paramFunctionStr, nil } -func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw LanguageWriter, NameSpace string, ClassName string, isGlobal bool, classdefinitions* []string) error { +func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw LanguageWriter, NameSpace string, ClassName string, isGlobal bool, classdefinitions *[]string) error { parameters := "" callparameters := "" returnvalues := "" - + var comments []string var implDeclarations []string - implDeclarations = append(implDeclarations, fmt.Sprintf("var err error = nil")) + implDeclarations = append(implDeclarations, fmt.Sprintf("var err error")) var implCasts []string implReturnValues := "" @@ -721,14 +737,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan errorReturn = errorReturn + fmt.Sprintf("h%s, ", param.ParamName) case "functiontype": errorReturn = errorReturn + fmt.Sprintf("0, ") - case "basicarray": - basicType, err := getGoBasicType(param.ParamClass) - if err != nil { - return err - } - errorReturn = errorReturn + fmt.Sprintf("make([]%s, 0), ", basicType) - case "structarray": - errorReturn = errorReturn + fmt.Sprintf("make([]s%s%s, 0), ", NameSpace, param.ParamClass) + case "basicarray", "structarray": + errorReturn = errorReturn + fmt.Sprint("nil, ") default: return fmt.Errorf("invalid method parameter type \"%s\" for %s.%s(%s)", param.ParamType, ClassName, method.MethodName, param.ParamName) } @@ -747,17 +757,20 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan requiresInitCall := false implCallParameters := "" implInitCallParameters := "" + implCallParameterCount := 0; + var implInitCallLines []string var classReturnImplementation []string classReturnVariables := "" classReturnString := "" - classReturnTypes := "" + classReturnTypes := "" for k := 0; k < len(method.Params); k++ { param := method.Params[k] - thisImplCallParamter := "" - thisInitImplCallParamter := "" + thisImplCallParameter := "" + thisInitImplCallParameter := "" + thisImplCallParameterCount := 1 switch param.ParamPass { case "in": if parameters != "" { @@ -769,14 +782,14 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan switch param.ParamType { case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64": - goParamName := "n"+param.ParamName + goParamName := "n" + param.ParamName comments = append(comments, fmt.Sprintf("* @param[in] %s - %s", goParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("%s %s", goParamName, param.ParamType) goParamFunction, err := paramFunction(param.ParamType, param.ParamPass) if err != nil { return err } - thisImplCallParamter = fmt.Sprintf(", %s(%s)", goParamFunction, goParamName) + thisImplCallParameter = fmt.Sprintf(", %s(%s)", goParamFunction, goParamName) callparameters = callparameters + goParamName case "bool": @@ -787,43 +800,43 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implDeclarations = append(implDeclarations, fmt.Sprintf("}")) implDeclarations = append(implDeclarations, fmt.Sprintf("")) parameters = parameters + fmt.Sprintf("b%s bool", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", UInt8InValue(n%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", UInt8InValue(n%s)", param.ParamName) callparameters = callparameters + "b" + param.ParamName case "single": comments = append(comments, fmt.Sprintf("* @param[in] f%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("f%s float32", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", Float32InValue(f%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", Float32InValue(f%s)", param.ParamName) callparameters = callparameters + "f" + param.ParamName case "double": comments = append(comments, fmt.Sprintf("* @param[in] d%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("d%s float64", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", Float64InValue(d%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", Float64InValue(d%s)", param.ParamName) callparameters = callparameters + "d" + param.ParamName case "pointer": comments = append(comments, fmt.Sprintf("* @param[in] n%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("n%s uint64", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", UInt64InValue(n%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", UInt64InValue(n%s)", param.ParamName) callparameters = callparameters + "n" + param.ParamName case "string": comments = append(comments, fmt.Sprintf("* @param[in] s%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("s%s string", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", StringInValue(s%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", StringInValue(s%s)", param.ParamName) callparameters = callparameters + "s" + param.ParamName case "enum": comments = append(comments, fmt.Sprintf("* @param[in] e%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("e%s E%s%s", param.ParamName, NameSpace, param.ParamClass) - thisImplCallParamter = fmt.Sprintf(", uintptr(e%s)", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", uintptr(e%s)", param.ParamName) callparameters = callparameters + "e" + param.ParamName case "struct": comments = append(comments, fmt.Sprintf("* @param[in] s%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("s%s s%s%s", param.ParamName, NameSpace, param.ParamClass) - thisImplCallParamter = fmt.Sprintf(", uintptr(unsafe.Pointer(&s%s))", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", uintptr(unsafe.Pointer(&s%s))", param.ParamName) callparameters = callparameters + "s" + param.ParamName case "basicarray": @@ -833,19 +846,28 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan } comments = append(comments, fmt.Sprintf("* @param[in] %s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("%s []%s", param.ParamName, basicType) - thisImplCallParamter = fmt.Sprintf(", 0, 0") + + implCasts = append(implCasts, fmt.Sprintf("var ptr%s uintptr = 0;", param.ParamName)) + implCasts = append(implCasts, fmt.Sprintf("len%s := uintptr (len(%s));", param.ParamName, param.ParamName)) + implCasts = append(implCasts, fmt.Sprintf("if (len%s > 0) {", param.ParamName)) + implCasts = append(implCasts, fmt.Sprintf(" ptr%s = uintptr(unsafe.Pointer(&%s[0]));", param.ParamName, param.ParamName)) + implCasts = append(implCasts, fmt.Sprintf("}")) + + thisImplCallParameter = fmt.Sprintf(", len%s, ptr%s", param.ParamName, param.ParamName) + thisImplCallParameterCount = 2 callparameters = callparameters + param.ParamName case "structarray": comments = append(comments, fmt.Sprintf("* @param[in] %s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("%s []s%s%s", param.ParamName, NameSpace, param.ParamClass) - thisImplCallParamter = fmt.Sprintf(", 0, 0") + thisImplCallParameter = fmt.Sprintf(", 0, 0") + thisImplCallParameterCount = 2 callparameters = callparameters + param.ParamName case "functiontype": comments = append(comments, fmt.Sprintf("* @param[in] p%s - %s", param.ParamName, param.ParamDescription)) parameters = parameters + fmt.Sprintf("p%s int64", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", 0") + thisImplCallParameter = fmt.Sprintf(", 0") callparameters = callparameters + "p" + param.ParamName case "class", "optionalclass": @@ -859,20 +881,20 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implCasts = append(implCasts, fmt.Sprintf("")) implCasts = append(implCasts, fmt.Sprintf("%sDLLHandle := implementation_%s.GetDLLInHandle()", param.ParamName, strings.ToLower(param.ParamName))) - if (param.ParamType == "class") { + if param.ParamType == "class" { implCasts = append(implCasts, fmt.Sprintf("if (%sDLLHandle == 0) {", param.ParamName)) - implCasts = append(implCasts, fmt.Sprintf(" err := fmt.Errorf(\"Handle must not be 0.\")", )) + implCasts = append(implCasts, fmt.Sprintf(" err := fmt.Errorf(\"Handle must not be 0.\")")) implCasts = append(implCasts, fmt.Sprintf(" return %s", errorReturn)) implCasts = append(implCasts, fmt.Sprintf("}")) } - thisImplCallParamter = fmt.Sprintf(", %sDLLHandle", param.ParamName) + thisImplCallParameter = fmt.Sprintf(", %sDLLHandle", param.ParamName) callparameters = callparameters + param.ParamName default: return fmt.Errorf("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, ClassName, method.MethodName, param.ParamName) } - thisInitImplCallParamter = thisImplCallParamter + thisInitImplCallParameter = thisImplCallParameter case "out", "return": comments = append(comments, fmt.Sprintf("* @return %s", param.ParamDescription)) @@ -887,13 +909,13 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan if err != nil { return err } - goParamName := "n"+param.ParamName + goParamName := "n" + param.ParamName returnvalues = returnvalues + fmt.Sprintf("%s, ", basicType) implDeclarations = append(implDeclarations, fmt.Sprintf("var %s %s = 0", goParamName, param.ParamType)) implReturnValues = implReturnValues + fmt.Sprintf("%s(%s), ", basicType, goParamName) - thisImplCallParamter = fmt.Sprintf(", %s(&%s)", goParamFunction, goParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", %s(&%s)", goParamFunction, goParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + goParamName + ", " classReturnString = classReturnString + goParamName + ", " @@ -904,8 +926,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implDeclarations = append(implDeclarations, fmt.Sprintf("var n%s uint64 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("n%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", UInt64OutValue(&n%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", UInt64OutValue(&n%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "n" + param.ParamName + ", " classReturnString = classReturnString + "n" + param.ParamName + ", " @@ -916,8 +938,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implDeclarations = append(implDeclarations, fmt.Sprintf("var b%s int64 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("(b%s != 0), ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", Int64OutValue(&b%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", Int64OutValue(&b%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "b" + param.ParamName + ", " classReturnString = classReturnString + "b" + param.ParamName + ", " @@ -928,8 +950,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implDeclarations = append(implDeclarations, fmt.Sprintf("var f%s float32 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("f%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", Float32OutValue(&f%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", Float32OutValue(&f%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "f" + param.ParamName + ", " classReturnString = classReturnString + "f" + param.ParamName + ", " @@ -940,8 +962,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implDeclarations = append(implDeclarations, fmt.Sprintf("var d%s float64 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("d%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", Float64OutValue(&d%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", Float64OutValue(&d%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "d" + param.ParamName + ", " classReturnString = classReturnString + "d" + param.ParamName + ", " @@ -951,13 +973,14 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan requiresInitCall = true implDeclarations = append(implDeclarations, fmt.Sprintf("var neededfor%s int64 = 0", param.ParamName)) implDeclarations = append(implDeclarations, fmt.Sprintf("var filledin%s int64 = 0", param.ParamName)) - - thisInitImplCallParamter = fmt.Sprintf(", Int64InValue(0), Int64OutValue(&neededfor%s), Int64InValue(0)", param.ParamName) + + thisInitImplCallParameter = fmt.Sprintf(", Int64InValue(0), Int64OutValue(&neededfor%s), Int64InValue(0)", param.ParamName) implInitCallLines = append(implInitCallLines, fmt.Sprintf("bufferSize%s := neededfor%s", param.ParamName, param.ParamName)) implInitCallLines = append(implInitCallLines, fmt.Sprintf("buffer%s := make([]byte, bufferSize%s)", param.ParamName, param.ParamName)) - thisImplCallParamter = fmt.Sprintf(", Int64InValue(bufferSize%s), Int64OutValue(&filledin%s), uintptr(unsafe.Pointer(&buffer%s[0]))", param.ParamName, param.ParamName, param.ParamName) + thisImplCallParameter = fmt.Sprintf(", Int64InValue(bufferSize%s), Int64OutValue(&filledin%s), uintptr(unsafe.Pointer(&buffer%s[0]))", param.ParamName, param.ParamName, param.ParamName) + thisImplCallParameterCount = 3 implReturnValues = implReturnValues + fmt.Sprintf("string(buffer%s[:(filledin%s-1)]), ", param.ParamName, param.ParamName) @@ -970,58 +993,50 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan returnvalues = returnvalues + fmt.Sprintf("E%s%s, ", NameSpace, param.ParamClass) implDeclarations = append(implDeclarations, fmt.Sprintf("var e%s uint64 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("E%s%s (e%s), ", NameSpace, param.ParamClass, param.ParamName) - thisImplCallParamter = fmt.Sprintf(", UInt64OutValue(&e%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", UInt64OutValue(&e%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "e" + param.ParamName + ", " classReturnString = classReturnString + "e" + param.ParamName + ", " classReturnTypes = classReturnTypes + fmt.Sprintf("E%s%s, ", NameSpace, param.ParamClass) - case "basicarray": - requiresInitCall = true - basicType, err := getGoBasicType(param.ParamClass) - if err != nil { - return err + case "basicarray", "structarray": + var arrayType string + if param.ParamType == "basicarray" { + var err error + arrayType, err = getGoBasicType(param.ParamClass) + if err != nil { + return err + } + } else { + arrayType = fmt.Sprintf("s%s%s", NameSpace, param.ParamClass) } - implDeclarations = append(implDeclarations, fmt.Sprintf("var neededfor%s int64 = 0", param.ParamName)) - implDeclarations = append(implDeclarations, fmt.Sprintf("var filledin%s int64 = 0", param.ParamName)) + requiresInitCall = true + needSizeVar := fmt.Sprintf("neededfor%s", param.ParamName) + implDeclarations = append(implDeclarations, fmt.Sprintf("var %s int64", needSizeVar)) bufferName := fmt.Sprintf("buffer%s", param.ParamName) - implDeclarations = append(implDeclarations, fmt.Sprintf("%s := make([]%s, 0)", bufferName, basicType)) - thisInitImplCallParamter = fmt.Sprintf(", Int64InValue(0), Int64OutValue(&neededfor%s), Int64InValue(0)", param.ParamName) - - implInitCallLines = append(implInitCallLines, fmt.Sprintf("bufferSize%s := neededfor%s", param.ParamName, param.ParamName)) - implInitCallLines = append(implInitCallLines, fmt.Sprintf("%s = make([]%s, bufferSize%s)", bufferName, basicType, param.ParamName)) + thisInitImplCallParameter = fmt.Sprintf(", 0, Int64OutValue(&%s), 0", needSizeVar) - thisImplCallParamter = fmt.Sprintf(", Int64InValue(bufferSize%s), Int64OutValue(&filledin%s), uintptr(unsafe.Pointer(&%s[0]))", param.ParamName, param.ParamName, bufferName) + implInitCallLines = append(implInitCallLines, fmt.Sprintf("%s := make([]%s, %s)", bufferName, arrayType, needSizeVar)) + thisImplCallParameter = fmt.Sprintf(", Int64InValue(%s), 0, uintptr(unsafe.Pointer(&%s[0]))", needSizeVar, bufferName) + thisImplCallParameterCount = 3 - returnvalues = returnvalues + fmt.Sprintf("[]%s, ", basicType) + returnvalues = returnvalues + fmt.Sprintf("[]%s, ", arrayType) implReturnValues = implReturnValues + fmt.Sprintf("%s, ", bufferName) classReturnVariables = classReturnVariables + bufferName + ", " classReturnString = classReturnString + bufferName + ", " - classReturnTypes = classReturnTypes + fmt.Sprintf("[]%s, ", basicType) - - case "structarray": - requiresInitCall = true - returnvalues = returnvalues + fmt.Sprintf("[]s%s%s, ", NameSpace, param.ParamClass) - implDeclarations = append(implDeclarations, fmt.Sprintf("array%s := make([]s%s%s, 0)", param.ParamName, NameSpace, param.ParamClass)) - implReturnValues = implReturnValues + fmt.Sprintf("array%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", 0, 0, 0") - thisInitImplCallParamter = thisImplCallParamter - - classReturnVariables = classReturnVariables + "array" + param.ParamName + ", " - classReturnString = classReturnString + "array" + param.ParamName + ", " - classReturnTypes = classReturnTypes + fmt.Sprintf("[]s%s%s, ", NameSpace, param.ParamClass) + classReturnTypes = classReturnTypes + fmt.Sprintf("[]%s, ", arrayType) case "functiontype": returnvalues = returnvalues + fmt.Sprintf("uint64, ") implDeclarations = append(implDeclarations, fmt.Sprintf("var p%s uint64 = 0", param.ParamName)) implReturnValues = implReturnValues + fmt.Sprintf("p%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", UInt64OutValue(&p%s)", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter - + thisImplCallParameter = fmt.Sprintf(", UInt64OutValue(&p%s)", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter + classReturnVariables = classReturnVariables + "p" + param.ParamName + ", " classReturnString = classReturnString + "p" + param.ParamName + ", " classReturnTypes = classReturnTypes + fmt.Sprintf("uint64, ") @@ -1030,8 +1045,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan returnvalues = returnvalues + fmt.Sprintf("s%s%s, ", NameSpace, param.ParamClass) implDeclarations = append(implDeclarations, fmt.Sprintf("var s%s s%s%s", param.ParamName, NameSpace, param.ParamClass)) implReturnValues = implReturnValues + fmt.Sprintf("s%s, ", param.ParamName) - thisImplCallParamter = fmt.Sprintf(", 0") - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", 0") + thisInitImplCallParameter = thisImplCallParameter classReturnVariables = classReturnVariables + "s" + param.ParamName + ", " classReturnString = classReturnString + "s" + param.ParamName + ", " @@ -1041,8 +1056,8 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan returnvalues = returnvalues + fmt.Sprintf("%sHandle, ", NameSpace) implDeclarations = append(implDeclarations, fmt.Sprintf("h%s := implementation.NewHandle()", param.ParamName)) - thisImplCallParamter = fmt.Sprintf(", h%s.GetDLLOutHandle()", param.ParamName) - thisInitImplCallParamter = thisImplCallParamter + thisImplCallParameter = fmt.Sprintf(", h%s.GetDLLOutHandle()", param.ParamName) + thisInitImplCallParameter = thisImplCallParameter implReturnValues = implReturnValues + fmt.Sprintf("h%s, ", param.ParamName) classReturnVariables = classReturnVariables + "h" + param.ParamName + ", " @@ -1061,8 +1076,13 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan return fmt.Errorf("invalid method parameter passing \"%s\" for %s.%s (%s)", param.ParamPass, ClassName, method.MethodName, param.ParamName) } - implCallParameters += thisImplCallParamter - implInitCallParameters += thisInitImplCallParamter + implCallParameters += thisImplCallParameter + implInitCallParameters += thisInitImplCallParameter + implCallParameterCount += thisImplCallParameterCount + if (implCallParameterCount > 18) { + return fmt.Errorf("too many function call parameters for Go Bindings in %s.%s (%s)", ClassName, method.MethodName, param.ParamName) + } + } w.Writeln("") @@ -1084,7 +1104,6 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan w.Writeln(" %s_%s(%s%s) (%serror)\n", ClassName, method.MethodName, handleparameter, parameters, returnvalues) } - // Implementation implmethodname := "implementation." + NameSpace + "_" implGetHandleFunction := "" @@ -1093,7 +1112,7 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan implGetHandleFunction = fmt.Sprintf(", implementation_%s.GetDLLInHandle()", strings.ToLower(ClassName)) } implmethodname += strings.ToLower(method.MethodName) - + if isGlobal { implw.Writeln("func (implementation *%sImplementation) %s(%s%s) (%serror) {", NameSpace, method.MethodName, handleparameter, parameters, returnvalues) } else { @@ -1130,7 +1149,7 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan *classdefinitions = append(*classdefinitions, fmt.Sprintf(" %serror := instance.Interface.%s_%s(instance.Handle%s)", classReturnVariables, ClassName, method.MethodName, callparameters)) } for _, line := range classReturnImplementation { - *classdefinitions = append(*classdefinitions, fmt.Sprintf(" %s", line )) + *classdefinitions = append(*classdefinitions, fmt.Sprintf(" %s", line)) } *classdefinitions = append(*classdefinitions, fmt.Sprintf(" return %serror", classReturnString)) *classdefinitions = append(*classdefinitions, fmt.Sprintf("}")) @@ -1138,4 +1157,3 @@ func writeGoMethod(method ComponentDefinitionMethod, w LanguageWriter, implw Lan return nil } - diff --git a/Source/buildimplementationcpp.go b/Source/buildimplementationcpp.go index 6fdf5f19..7aaa35db 100644 --- a/Source/buildimplementationcpp.go +++ b/Source/buildimplementationcpp.go @@ -263,12 +263,6 @@ func buildCPPInternalException(wHeader LanguageWriter, wImpl LanguageWriter, Nam wImpl.Writeln(" m_errorCode = errorCode;"); wImpl.Writeln("}"); wImpl.Writeln(""); - wImpl.Writeln("E%sInterfaceException::E%sInterfaceException(%sResult errorCode, std::string errorMessage)", NameSpace, NameSpace, NameSpace); - wImpl.Writeln(" : m_errorMessage(errorMessage + \" (\" + std::to_string (errorCode) + \")\")"); - wImpl.Writeln("{"); - wImpl.Writeln(" m_errorCode = errorCode;"); - wImpl.Writeln("}"); - wImpl.Writeln(""); wImpl.Writeln("%sResult E%sInterfaceException::getErrorCode ()", NameSpace, NameSpace); wImpl.Writeln("{"); wImpl.Writeln(" return m_errorCode;"); @@ -337,6 +331,13 @@ func writeCPPClassInterface(component ComponentDefinition, class ComponentDefini classInterfaceName := fmt.Sprintf("I%s%s", ClassIdentifier, class.ClassName) w.Writeln("class %s%s{", classInterfaceName, parentClassString) + + if (component.isStringOutBaseClass(class)) { + w.Writeln("private:") + w.Writeln(" std::auto_ptr m_ParameterCache;") + + } + w.Writeln("public:") if (component.isBaseClass(class)) { @@ -390,6 +391,28 @@ func writeCPPClassInterface(component ComponentDefinition, class ComponentDefini } } + if (component.isStringOutBaseClass(class)) { + + w.Writeln("") + w.Writeln(" /**") + w.Writeln(" * %s::_setCache - set parameter cache of object", classInterfaceName) + w.Writeln(" */") + w.Writeln(" void _setCache(ParameterCache * pCache)") + w.Writeln(" {") + w.Writeln(" m_ParameterCache.reset(pCache);") + w.Writeln(" }") + w.Writeln("") + + w.Writeln(" /**") + w.Writeln(" * %s::_getCache - returns parameter cache of object", classInterfaceName) + w.Writeln(" */") + w.Writeln(" ParameterCache* _getCache()") + w.Writeln(" {") + w.Writeln(" return m_ParameterCache.get();") + w.Writeln(" }") + w.Writeln("") + } + for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] methodstring, _, err := buildCPPInterfaceMethodDeclaration(method, class.ClassName, NameSpace, ClassIdentifier, BaseName, w.IndentString, false, true, true) @@ -422,6 +445,60 @@ func writeClassDefinitions(component ComponentDefinition, w LanguageWriter, Name } } + +func writeParameterCacheDefinitions(component ComponentDefinition, w LanguageWriter, NameSpaceImplementation string, ClassIdentifier string) { + + w.Writeln("") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Parameter Cache definitions") + w.Writeln("**************************************************************************************************************************/") + w.Writeln("") + w.Writeln("class ParameterCache {") + w.Writeln(" public:") + w.Writeln(" virtual ~ParameterCache() {}") + w.Writeln("};") + w.Writeln("") + + maxParamCount := component.countMaxOutParameters (); + + for paramCount := uint32(1); paramCount <= maxParamCount; paramCount++ { + + classString := "class T1"; + constructorString := "const T1 & param1"; + assignmentString := "m_param1 (param1)"; + retrieveString := "T1 & param1"; + for paramIdx := uint32(2); paramIdx <= paramCount; paramIdx++ { + classString += fmt.Sprintf (", class T%d", paramIdx); + constructorString += fmt.Sprintf (", const T%d & param%d", paramIdx, paramIdx); + assignmentString += fmt.Sprintf (", m_param%d (param%d)", paramIdx, paramIdx); + retrieveString += fmt.Sprintf (", T%d & param%d", paramIdx, paramIdx); + } + + w.Writeln("template <%s> class ParameterCache_%d : public ParameterCache {", classString, paramCount); + w.Writeln(" private:") + for paramIdx := uint32(1); paramIdx <= paramCount; paramIdx++ { + w.Writeln(" T%d m_param%d;", paramIdx, paramIdx) + } + w.Writeln(" public:") + w.Writeln(" ParameterCache_%d (%s)", paramCount, constructorString) + w.Writeln(" : %s", assignmentString) + w.Writeln(" {") + w.Writeln(" }") + w.Writeln("") + w.Writeln(" void retrieveData (%s)", retrieveString) + w.Writeln(" {") + for paramIdx := uint32(1); paramIdx <= paramCount; paramIdx++ { + w.Writeln(" param%d = m_param%d;", paramIdx, paramIdx) + } + w.Writeln(" }") + w.Writeln("};") + w.Writeln("") + + } + +} + + func buildCPPInterfaces(component ComponentDefinition, w LanguageWriter, NameSpaceImplementation string, ClassIdentifier string) error { NameSpace := component.NameSpace BaseName := component.BaseName @@ -457,6 +534,8 @@ func buildCPPInterfaces(component ComponentDefinition, w LanguageWriter, NameSpa w.Writeln("") w.Writeln("") + writeParameterCacheDefinitions(component, w, NameSpaceImplementation, ClassIdentifier) + writeClassDefinitions(component, w, NameSpaceImplementation, ClassIdentifier) w.Writeln("") @@ -802,6 +881,29 @@ func buildCPPInterfaceWrapper(component ComponentDefinition, w LanguageWriter, N return nil } + +func buildOutCacheTemplateParameters (method ComponentDefinitionMethod, NameSpace string) (string, error) { + result := ""; + + for i := 0; i < len (method.Params); i++ { + param := method.Params[i]; + + if ((param.ParamPass == "out") || (param.ParamPass == "return")) { + if (result != "") { + result += ", "; + } + + cppParamType := getCppParamType(param, NameSpace, true); + result += cppParamType; + } + + + } + + return result, nil; +} + + func writeCImplementationMethod(component ComponentDefinition, method ComponentDefinitionMethod, w LanguageWriter, BaseName string, NameSpace string, NameSpaceImplementation string, ClassIdentifier string, ClassName string, BaseClassName string, isGlobal bool, doJournal bool, isSpecialFunction int) error { CMethodName := "" cParams, err := GenerateCParameters(method, ClassName, NameSpace) @@ -829,7 +931,7 @@ func writeCImplementationMethod(component ComponentDefinition, method ComponentD callCPPFunctionCode := make([]string, 0) - checkInputCPPFunctionCode, preCallCPPFunctionCode, postCallCPPFunctionCode, returnVariable, callParameters, err := generatePrePostCallCPPFunctionCode(component, method, NameSpace, ClassIdentifier, ClassName, BaseClassName) + checkInputCPPFunctionCode, preCallCPPFunctionCode, postCallCPPFunctionCode, returnVariable, callParameters, outCallParameters, err := generatePrePostCallCPPFunctionCode(component, method, NameSpace, ClassIdentifier, ClassName, BaseClassName) if err != nil { return err } @@ -865,7 +967,50 @@ func writeCImplementationMethod(component ComponentDefinition, method ComponentD if err != nil { return err } - callCPPFunctionCode = append(callCPPFunctionCode, callCode) + + stringOutParameters := method.getStringOutParameters (); + outParameterCount := method.countOutParameters (); + bHasCacheCall := (len (stringOutParameters) > 0) && (!isGlobal); + + if (bHasCacheCall) { + + templateParameters, err := buildOutCacheTemplateParameters (method, NameSpace); + if err != nil { + return err + } + + cacheClassName := fmt.Sprintf ("ParameterCache_%d<%s>", outParameterCount, templateParameters); + cacheClassParameters := outCallParameters; + cacheCallCondition := ""; + + for i := 0; i < len (stringOutParameters); i++ { + if (i > 0) { + cacheCallCondition = cacheCallCondition + " || "; + } + + cacheCallCondition += fmt.Sprintf ("(p%sBuffer == nullptr)", stringOutParameters[i]); + } + + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("bool isCacheCall = %s;", cacheCallCondition)); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("if (isCacheCall) {")); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" " + callCode)) + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" pI%s->_setCache (new %s (%s));", ClassName, cacheClassName, cacheClassParameters)); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("}")); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("else {")); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" auto cache = dynamic_cast<%s*> (pI%s->_getCache ());", cacheClassName, ClassName)); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" if (cache == nullptr)")); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" throw E%sInterfaceException(%s_ERROR_INVALIDCAST);", NameSpace, strings.ToUpper(NameSpace)) ); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" cache->retrieveData (%s);", cacheClassParameters)); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf (" pI%s->_setCache (nullptr);", ClassName)); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("}")); + callCPPFunctionCode = append(callCPPFunctionCode, fmt.Sprintf ("")); + + } else { + + callCPPFunctionCode = append(callCPPFunctionCode, callCode); + + } + } journalInitFunctionCode := make([]string, 0) @@ -1015,7 +1160,7 @@ func buildCPPStubClass(component ComponentDefinition, class ComponentDefinitionC stubheaderw.Writeln("") if (component.isBaseClass(class)) { - stubheaderw.Writeln(" std::vector m_errors;") + stubheaderw.Writeln(" std::auto_ptr m_pLastError;") stubheaderw.Writeln("") } stubheaderw.Writeln(" /**") @@ -1186,7 +1331,7 @@ func buildCPPInterfaceMethodDeclaration(method ComponentDefinitionMethod, classN parameters := "" returntype := "void" commentcode := "" - + templateimplementation := "" for k := 0; k < len(method.Params); k++ { @@ -1428,10 +1573,11 @@ func getCppParamType (param ComponentDefinitionParam, NameSpace string, isInput return ""; } -func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method ComponentDefinitionMethod, NameSpace string, ClassIdentifier string, ClassName string, BaseClassName string) ([]string, []string, []string, string, string, error) { +func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method ComponentDefinitionMethod, NameSpace string, ClassIdentifier string, ClassName string, BaseClassName string) ([]string, []string, []string, string, string, string, error) { preCallCode := make([]string, 0) postCallCode := make([]string, 0) callParameters := "" + outCallParameters := ""; returnVariable := "" checkInputCode := make([]string, 0) IBaseClassName := fmt.Sprintf("I%s%s", ClassIdentifier, BaseClassName) @@ -1491,13 +1637,17 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co callParameters = callParameters + variableName default: - return checkInputCode, preCallCode, postCallCode, "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) + return checkInputCode, preCallCode, postCallCode, "", "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) } case "out": if callParameters != "" { callParameters = callParameters + ", " } + if outCallParameters != "" { + outCallParameters = outCallParameters + ", " + } + switch param.ParamType { @@ -1505,6 +1655,7 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co checkInputCode = append(checkInputCode, fmt.Sprintf("if (!p%s)", param.ParamName)) checkInputCode = append(checkInputCode, fmt.Sprintf(" throw E%sInterfaceException (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) callParameters = callParameters + "*p" + param.ParamName + outCallParameters = outCallParameters + "*p" + param.ParamName case "basicarray", "structarray": checkInputCode = append(checkInputCode, fmt.Sprintf("if ((!p%sBuffer) && !(p%sNeededCount))", param.ParamName, param.ParamName)) @@ -1517,6 +1668,7 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co preCallCode = append(preCallCode, fmt.Sprintf("std::string %s(\"\");", variableName)) callParameters = callParameters + variableName + outCallParameters = outCallParameters + variableName postCallCode = append(postCallCode, fmt.Sprintf("if (p%sNeededChars)", param.ParamName)) postCallCode = append(postCallCode, fmt.Sprintf(" *p%sNeededChars = (%s_uint32) (%s.size()+1);", param.ParamName, NameSpace, variableName)) @@ -1541,18 +1693,24 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co postCallCode = append(postCallCode, fmt.Sprintf("%s->%s(%s.get());", theWrapper, acqurireMethod, outVarName)) postCallCode = append(postCallCode, fmt.Sprintf("*%s = %s->GetHandle();", variableName, outVarName)); callParameters = callParameters + outVarName + outCallParameters = outCallParameters + outVarName } else { preCallCode = append(preCallCode, fmt.Sprintf("%s* pBase%s(nullptr);", IBaseClassName, param.ParamName)) postCallCode = append(postCallCode, fmt.Sprintf("*%s = (%s*)(pBase%s);", variableName, IBaseClassName, param.ParamName)); callParameters = callParameters + "pBase" + param.ParamName + outCallParameters = outCallParameters + "pBase" + param.ParamName } default: - return checkInputCode, preCallCode, postCallCode, "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) + return checkInputCode, preCallCode, postCallCode, "", "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) } case "return": + + if outCallParameters != "" { + outCallParameters = outCallParameters + ", " + } switch param.ParamType { @@ -1561,12 +1719,14 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co checkInputCode = append(checkInputCode, fmt.Sprintf(" throw E%sInterfaceException (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) returnVariable = fmt.Sprintf("*p%s", param.ParamName) + outCallParameters = outCallParameters + returnVariable; case "struct": checkInputCode = append(checkInputCode, fmt.Sprintf("if (p%s == nullptr)", param.ParamName)) checkInputCode = append(checkInputCode, fmt.Sprintf("throw E%sInterfaceException (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) returnVariable = fmt.Sprintf("*p%s", param.ParamName) + outCallParameters = outCallParameters + returnVariable; case "string": checkInputCode = append(checkInputCode, fmt.Sprintf("if ( (!p%sBuffer) && !(p%sNeededChars) )", param.ParamName, param.ParamName)) @@ -1574,6 +1734,7 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co preCallCode = append(preCallCode, fmt.Sprintf("std::string %s(\"\");", variableName)) returnVariable = variableName + outCallParameters = outCallParameters + returnVariable; postCallCode = append(postCallCode, fmt.Sprintf("if (p%sNeededChars)", param.ParamName)) postCallCode = append(postCallCode, fmt.Sprintf(" *p%sNeededChars = (%s_uint32) (%s.size()+1);", param.ParamName, NameSpace, variableName)) @@ -1602,17 +1763,19 @@ func generatePrePostCallCPPFunctionCode(component ComponentDefinition, method Co returnVariable = fmt.Sprintf("pBase%s", param.ParamName) postCallCode = append(postCallCode, fmt.Sprintf("*%s = (%s*)(pBase%s);", variableName, IBaseClassName, param.ParamName)); } + outCallParameters = outCallParameters + returnVariable; + default: - return checkInputCode, preCallCode, postCallCode, "", "", fmt.Errorf("invalid method parameter type \"%s\" for %s.%s(%s)", param.ParamType, ClassName, method.MethodName, param.ParamName) + return checkInputCode, preCallCode, postCallCode, "", "", "", fmt.Errorf("invalid method parameter type \"%s\" for %s.%s(%s)", param.ParamType, ClassName, method.MethodName, param.ParamName) } default: - return checkInputCode, preCallCode, postCallCode, "", "", fmt.Errorf("invalid method parameter passing \"%s\" for %s.%s(%s)", param.ParamPass, ClassName, method.MethodName, param.ParamName) + return checkInputCode, preCallCode, postCallCode, "", "", "", fmt.Errorf("invalid method parameter passing \"%s\" for %s.%s(%s)", param.ParamPass, ClassName, method.MethodName, param.ParamName) } } - return checkInputCode, preCallCode, postCallCode, returnVariable, callParameters, nil + return checkInputCode, preCallCode, postCallCode, returnVariable, callParameters, outCallParameters, nil } func generateCallCPPFunctionCode(method ComponentDefinitionMethod, NameSpace string, ClassIdentifier string, ClassName string, returnVariable string, callParameters string, isGlobal bool) (string, error) { diff --git a/Source/componentdefinition.go b/Source/componentdefinition.go index 0c74eb78..6fba0ce7 100644 --- a/Source/componentdefinition.go +++ b/Source/componentdefinition.go @@ -116,6 +116,7 @@ type ComponentDefinitionGlobal struct { ComponentDiffableElement XMLName xml.Name `xml:"global"` BaseClassName string `xml:"baseclassname,attr"` + StringOutBaseClassName string `xml:"stringoutclassname,attr"` ErrorMethod string `xml:"errormethod,attr"` ReleaseMethod string `xml:"releasemethod,attr"` AcquireMethod string `xml:"acquiremethod,attr"` @@ -691,7 +692,11 @@ func (component *ComponentDefinition) checkMethod(method ComponentDefinitionMeth } } - + + + if ((len (method.getStringOutParameters ()) > 0) && (len (method.getArrayOutParameters ()) > 0)) { + return fmt.Errorf ("String and Array out parameters for method \"%s.%s\"", className, method.MethodName); + } return nil } @@ -1238,3 +1243,96 @@ func (component *ComponentDefinition) baseClass() (ComponentDefinitionClass) { log.Fatal("No base class available") return out } + +func (component *ComponentDefinition) isStringOutBaseClass(class ComponentDefinitionClass) (bool) { + return class.ClassName == component.Global.StringOutBaseClassName +} + + +func (method *ComponentDefinitionMethod) countOutParameters() (uint32) { + + var outParameters uint32; + outParameters = 0; + + for i := 0; i < len(method.Params); i++ { + if ((method.Params[i].ParamPass == "out") || (method.Params[i].ParamPass == "return")) { + outParameters++; + } + } + + return outParameters; +} + + +func (method *ComponentDefinitionMethod) getStringOutParameters() ([]string) { + + var outParameters []string; + + for i := 0; i < len(method.Params); i++ { + if (method.Params[i].ParamType == "string") { + if ((method.Params[i].ParamPass == "out") || (method.Params[i].ParamPass == "return")) { + outParameters = append (outParameters, method.Params[i].ParamName); + } + } + } + + return outParameters; +} + +func (method *ComponentDefinitionMethod) getArrayOutParameters() ([]string) { + + var outParameters []string; + + for i := 0; i < len(method.Params); i++ { + if ((method.Params[i].ParamType == "basicarray") || (method.Params[i].ParamType == "structarray")) { + if ((method.Params[i].ParamPass == "out") || (method.Params[i].ParamPass == "return")) { + outParameters = append (outParameters, method.Params[i].ParamName); + } + } + } + + return outParameters; +} + + +func (class *ComponentDefinitionClass) countMaxOutParameters() (uint32) { + + var maxOutParameters uint32; + maxOutParameters = 0; + + for i := 0; i < len(class.Methods); i++ { + outParameters := class.Methods[i].countOutParameters (); + if (outParameters > maxOutParameters) { + maxOutParameters = outParameters; + } + } + + return maxOutParameters; +} + +func (component *ComponentDefinition) countMaxOutParameters() (uint32) { + + var maxOutParameters uint32; + maxOutParameters = 0; + + classes := component.Classes + for i := 0; i < len(classes); i++ { + class := classes[i] + + outParameters := class.countMaxOutParameters (); + if (outParameters > maxOutParameters) { + maxOutParameters = outParameters; + } + } + + methods := component.Global.Methods; + for i := 0; i < len(methods); i++ { + outParameters := methods[i].countOutParameters (); + if (outParameters > maxOutParameters) { + maxOutParameters = outParameters; + } + } + + return maxOutParameters; +} +