Fix typed pointer casting: .assumingMemoryBound for C functions, remove double g_object_ref_sink in constructors
This commit is contained in:
parent
4a60aff56d
commit
50a42b2d83
5 changed files with 47 additions and 23 deletions
|
|
@ -225,16 +225,18 @@ public struct CodeGenerator {
|
|||
let parentClause = cls.parent.map { ": \($0)" } ?? ""
|
||||
swift += "public \(classKeyword) \(cls.name)\(parentClause) {\n"
|
||||
|
||||
let cPointer = "pointer.assumingMemoryBound(to: \(cls.cType).self)"
|
||||
|
||||
swift += """
|
||||
let pointer: UnsafeMutableRawPointer
|
||||
|
||||
public init(pointer: UnsafeMutableRawPointer) {
|
||||
g_object_ref_sink(pointer)
|
||||
g_object_ref_sink(\(cPointer))
|
||||
self.pointer = pointer
|
||||
}
|
||||
|
||||
deinit {
|
||||
g_object_unref(pointer)
|
||||
g_object_unref(\(cPointer))
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -267,7 +269,7 @@ public struct CodeGenerator {
|
|||
let returnTypeStr = fn.returnType == .void ? "" : " -> \(Self.typeToSwift(fn.returnType))"
|
||||
let returnStmt = fn.returnType == .void ? "" : "return "
|
||||
let args = params.map { p -> String in
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames)
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames, cType: p.cType)
|
||||
}.joined(separator: ", ")
|
||||
let cCall = "\(fn.cIdentifier)(\(args))"
|
||||
let wrappedReturn = Self.wrapCReturnValue(callExpression: cCall, returnType: fn.returnType)
|
||||
|
|
@ -312,12 +314,11 @@ public struct CodeGenerator {
|
|||
"\(Self.swiftifyParameterName(p.name)): \(Self.typeToSwift(p.type))"
|
||||
}.joined(separator: ", ")
|
||||
let args = params.map { p -> String in
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames)
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames, cType: p.cType)
|
||||
}.joined(separator: ", ")
|
||||
swift += """
|
||||
\(methodVisibility) convenience init(\(methodName): String? = nil, \(paramList)) {
|
||||
let ptr = \(method.cIdentifier)(\(args))
|
||||
g_object_ref_sink(ptr)
|
||||
self.init(pointer: ptr!)
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +330,7 @@ public struct CodeGenerator {
|
|||
}.joined(separator: ", ")
|
||||
let returnTypeStr = method.returnType == .void ? "" : " -> \(Self.typeToSwift(method.returnType))"
|
||||
let returnStmt = method.returnType == .void ? "" : "return "
|
||||
let cCall = Self.generateCFunctionCall(method: method, instancePointer: "pointer", classTypeNames: classTypeNames)
|
||||
let cCall = Self.generateCFunctionCall(method: method, instancePointer: "pointer", classTypeNames: classTypeNames, cType: cls.cType)
|
||||
|
||||
swift += """
|
||||
\(methodVisibility) func \(methodName)(\(paramList))\(returnTypeStr) {
|
||||
|
|
@ -546,7 +547,7 @@ public struct CodeGenerator {
|
|||
let returnStmt = fn.returnType == .void ? "" : "return "
|
||||
|
||||
let args = params.map { p -> String in
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames)
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames, cType: p.cType)
|
||||
}.joined(separator: ", ")
|
||||
let cCall = "\(fn.cIdentifier)(\(args))"
|
||||
let wrappedReturn = Self.wrapCReturnValue(callExpression: cCall, returnType: fn.returnType)
|
||||
|
|
@ -587,7 +588,7 @@ public struct CodeGenerator {
|
|||
get {
|
||||
var value = GValue()
|
||||
g_value_init(&value, \(cTypeName))
|
||||
g_object_get_property(pointer, "\(girPropName)", &value)
|
||||
g_object_get_property(pointer.assumingMemoryBound(to: GObject.self), "\(girPropName)", &value)
|
||||
let result = \(getterFunc)(&value)
|
||||
g_value_unset(&value)
|
||||
return result
|
||||
|
|
@ -596,7 +597,7 @@ public struct CodeGenerator {
|
|||
var value = GValue()
|
||||
g_value_init(&value, \(cTypeName))
|
||||
\(setterFunc)(&value, newValue)
|
||||
g_object_set_property(pointer, "\(girPropName)", &value)
|
||||
g_object_set_property(pointer.assumingMemoryBound(to: GObject.self), "\(girPropName)", &value)
|
||||
g_value_unset(&value)
|
||||
}
|
||||
}
|
||||
|
|
@ -608,7 +609,7 @@ public struct CodeGenerator {
|
|||
public var \(propName): \(swiftType) {
|
||||
var value = GValue()
|
||||
g_value_init(&value, \(cTypeName))
|
||||
g_object_get_property(pointer, "\(girPropName)", &value)
|
||||
g_object_get_property(pointer.assumingMemoryBound(to: GObject.self), "\(girPropName)", &value)
|
||||
let result = \(getterFunc)(&value)
|
||||
g_value_unset(&value)
|
||||
return result
|
||||
|
|
@ -623,7 +624,7 @@ public struct CodeGenerator {
|
|||
var value = GValue()
|
||||
g_value_init(&value, \(cTypeName))
|
||||
\(setterFunc)(&value, newValue)
|
||||
g_object_set_property(pointer, "\(girPropName)", &value)
|
||||
g_object_set_property(pointer.assumingMemoryBound(to: GObject.self), "\(girPropName)", &value)
|
||||
g_value_unset(&value)
|
||||
}
|
||||
}
|
||||
|
|
@ -723,13 +724,12 @@ public struct CodeGenerator {
|
|||
"\(Self.swiftifyParameterName(p.name)): \(Self.typeToSwift(p.type))"
|
||||
}.joined(separator: ", ")
|
||||
let args = params.map { p -> String in
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames)
|
||||
Self.cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames, cType: p.cType)
|
||||
}.joined(separator: ", ")
|
||||
|
||||
return """
|
||||
public convenience init(\(paramList)) {
|
||||
let ptr = \(constructor.cIdentifier)(\(args))
|
||||
g_object_ref_sink(ptr)
|
||||
self.init(pointer: ptr!)
|
||||
}
|
||||
|
||||
|
|
@ -739,11 +739,14 @@ public struct CodeGenerator {
|
|||
|
||||
// MARK: - C Function Call Generation
|
||||
|
||||
public static func generateCFunctionCall(method: Method, instancePointer: String, classTypeNames: Set<String>? = nil) -> String {
|
||||
public static func generateCFunctionCall(method: Method, instancePointer: String, classTypeNames: Set<String>? = nil, cType: String = "") -> String {
|
||||
let typedInstancePointer = (instancePointer == "pointer" && !cType.isEmpty)
|
||||
? "pointer.assumingMemoryBound(to: \(cType).self)"
|
||||
: instancePointer
|
||||
let sortedParams = Self.nonVarargParameters(method.parameters)
|
||||
let args = sortedParams.map { p -> String in
|
||||
if p.isInstanceParameter { return instancePointer }
|
||||
return cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames)
|
||||
if p.isInstanceParameter { return typedInstancePointer }
|
||||
return cParameterExpression(name: Self.swiftifyParameterName(p.name), type: p.type, classTypeNames: classTypeNames, cType: p.cType)
|
||||
}.joined(separator: ", ")
|
||||
|
||||
let cFuncCall = "\(method.cIdentifier)(\(args))"
|
||||
|
|
@ -763,7 +766,12 @@ public struct CodeGenerator {
|
|||
/// - classTypeNames: The set of class type names that have a `.pointer`
|
||||
/// property. Types NOT in this set are passed directly.
|
||||
/// - Returns: A Swift expression string for the C function argument.
|
||||
private static func cParameterExpression(name: String, type: GIRType, classTypeNames: Set<String>? = nil) -> String {
|
||||
private static func typedPointerCast(expression: String, cType: String) -> String {
|
||||
let stripped = cType.hasSuffix("*") ? String(cType.dropLast()) : cType
|
||||
return "\(expression).assumingMemoryBound(to: \(stripped).self)"
|
||||
}
|
||||
|
||||
private static func cParameterExpression(name: String, type: GIRType, classTypeNames: Set<String>? = nil, cType: String = "") -> String {
|
||||
let usesPointer: Bool
|
||||
switch type {
|
||||
case .typeRef(let refName, _):
|
||||
|
|
@ -782,10 +790,22 @@ public struct CodeGenerator {
|
|||
|
||||
switch type {
|
||||
case .typeRef:
|
||||
return usesPointer ? "\(name).pointer" : name
|
||||
if usesPointer {
|
||||
if !cType.isEmpty {
|
||||
return Self.typedPointerCast(expression: "\(name).pointer", cType: cType)
|
||||
}
|
||||
return "\(name).pointer"
|
||||
}
|
||||
return name
|
||||
case .optional(let inner):
|
||||
if case .typeRef = inner {
|
||||
return usesPointer ? "\(name)?.pointer" : name
|
||||
if usesPointer {
|
||||
if !cType.isEmpty {
|
||||
return "\(name)?.pointer.map { \(Self.typedPointerCast(expression: "$0", cType: cType)) }"
|
||||
}
|
||||
return "\(name)?.pointer"
|
||||
}
|
||||
return name
|
||||
}
|
||||
return name
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -222,8 +222,12 @@ final class GIRXMLDelegate: NSObject, XMLParserDelegate {
|
|||
case "type":
|
||||
let typeName = attributeDict["name"] ?? "none"
|
||||
let resolvedType = parseGIRType(typeName)
|
||||
let cType = attributeDict["c:type"] ?? ""
|
||||
if currentParameter != nil {
|
||||
currentParameter?.type = resolvedType
|
||||
if !cType.isEmpty {
|
||||
currentParameter?.cType = cType
|
||||
}
|
||||
} else if currentReturnType != nil {
|
||||
currentReturnType = resolvedType
|
||||
} else if currentProperty != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue