UPDATE: SUCCESS!

Since I sent that last email. I had a little break through. 

Then GNUStep ObjC function class_getMethodImplementation (Apple also has 
function class_getMethodImplementation_stret that is evidently not used in 
GNUStep and is just a stub) and allows one to look up the C function that is 
precisely used with the function. 

So I created a nice Swift version of this lookup. 
public func objc_smart_getIMP<T>(object: GNUStepNSObjectWrapper, selector: 
String) -> T? {
        let c = object_getClass(&object._nsobjptr!.pointee)
        let v = class_getMethodImplementation(c, sel_getUid(selector))
        let rt: T? = unsafeBitCast(v, to: T.self)
        return rt
}

And then in the the var frame property of my NSView wrapper the following 
public var frame: CGRect {
                get {
                        var imp:  (@convention(c) (id, SEL) -> (CGRect))? = 
objc_smart_getIMP(object: self, selector: "frame")
                        if let rtn = imp?(&self._nsobjptr!.pointee, 
sel_getUid("frame")) {
                                return rtn
                        }
                        return .init(x: 0, y: 0, width: 0, height: 0)
                }
                set {
                        guard let selfPtr = self._nsobjptr else {return}
                        let _: Any? = objc_smart_sendMessage(object: self, 
selector: "setFrame:", value1: newValue)
                }
}

RESULT: It worked!

When Swift Macros are working on Linux, this could be a Macro that generates 
everything we need. Maybe @GNUStepPropertyWrapper("frame", "getFrame") We could 
also have @GNUStepMethodWrapper that automatically wraps the method callers. 



> On Aug 8, 2023, at 7:48 PM, [email protected] wrote:
> 
> One of the issues that I am identifying is trying to manage the functions 
> `objc_msgSend ` and `objc_msgSend_stret `. I did a write up on my GitHub for 
> this project, and (as of right now) am trying to come up with solutions to 
> getting the right memory out of calls to `objc_msgSend ` and 
> `objc_msgSend_stret `. 
> 
> Basically I need a way to make objc_msgSend_stret more generic. 
> 
> Also what datatype size does objc_msgSend_stret service vs objc_msgSend. I am 
> assuming, that objc_msgSend is good for pointers and datives that are the 
> size of pointers?
> 
> You can view my evolving discussion with myself at 
> https://github.com/austintatiousness/GNUStepSwiftBridge
> 
> - Austin
> objc_msgSend and objc_msgSend_stret
> 
> objc_msgSend() is a c function used by the Objective-C runtime to send 
> messages. Unfortunately it has a variable arguments which cannot be imported 
> into Swift. To overcome this, I have created some specialized versions of of 
> objc_msgSend that have different number of arguments. These can be found in 
> the ObjCSwiftInterop.c file.
> 
> Ultimately, I would like a swift version of this which more intelligently 
> decides how to map the values. I started work on this, in the AppKit.swift 
> file called func objc_smart_sendMessage<T>(object: 
> NSObjectGNUStepSwiftBridge, selector: String,  value1: Any?, value2: Any?, 
> value3: Any?, value4: Any?, value5: Any?, value6: Any?, value7: Any?, value8: 
> Any?, value9: Any?) -> T?
> 
> This solves the problem that we have to send messages of arbitrary side, but 
> it does not solve the issues around casting, and that two separate functions 
> objc_msgSend and objc_msgSend_stret depending on which type we are going to 
> get back from.
> 
>  
> <https://github.com/austintatiousness/GNUStepSwiftBridge/blob/main/README.md#casting>CASTING
> 
> Just some thoughts and notes: Please correct me where I am wrong or 
> misunderstanding.
> 
> objc_msgSend and objc_msgSend_stret are very difficult functions to properly 
> import into Swift. objc_msgSend is used for messages that return Objective-C 
> classes, and simple data values that have the same size as id . From what I 
> understand, both require the the function to be properly cast to work and 
> because they are implemented in assembly and they are doing some magic with 
> the registers to properly get the result. objc_msgSend returns void* but 
> objc_msgSend_stret on GNUStep's runtime returns void. Before you can use 
> objc_msgSend_stret, you have to cast it to a function that returns the value 
> you are expecting.
> 
> UIView *view = [[NSView alloc] initWithFrame:NSRectZero];
> 
> NSRect (*sendRectFn)(id receiver, SEL operation);
> sendRectFn = (NSRect(*)(id, SEL))objc_msgSend_stret;
> NSRect frame = sendRectFn(view, @selector(frame));
> Idea 1: THIS DOES NOT WORK. I really have no idea what I am doing.
> 
> void* forSwift_objcMsgSend_stret(id ID, SEL cmd, int64_t returnSize) {
>       void* itemArr = malloc(returnSize);
>       void* (*sendRectFn)(id receiver, SEL operation);
>       sendRectFn = (void(*)(id, SEL))objc_msgSend_stret;
>       itemArr = sendRectFn(ID, cmd);
>       return itemArr;
> }
> What we need to be able to do is express this in Swift using
> 
> I do not know how the objc_msgSend_stret knows what the returned data type 
> should be.
> 
>> On Aug 8, 2023, at 4:56 AM, Gregory Casamento <[email protected]> 
>> wrote:
>> 
>> M A,
>> 
>> I guess you could consider the issues and such on github as a todo list.  
>> You are welcome to take on any tasks on there if you like.  Each repo has 
>> it's own "Issues" tab where you can see what issues are outstanding.   Or if 
>> you can think of features that you think might be useful, please discuss it 
>> here and we can all work together to make it happen if it sounds reasonable.
>> 
>> Wrapping an ObjC class around swift sounds interesting, though most people 
>> go the other way around these days... Swift->ObjC.
>> 
>> Yours, GC
>> 
>> On Mon, Aug 7, 2023 at 1:58 PM M A <[email protected] 
>> <mailto:[email protected]>> wrote:
>>> A to do list would be a great edition to this project's website.
>>> 
>>> One thing I would add it making a program that can wrap an Objective-c 
>>> class around Swift code. There are just too many classes and methods to do 
>>> it all by hand.
>>> 
>>> > On Aug 7, 2023, at 1:51 PM, Gregory Casamento <[email protected] 
>>> > <mailto:[email protected]>> wrote:
>>> > 
>>> > I am extremely impressed!!!  This is great!  Please let me know if I can 
>>> > help in any way.
>>> > 
>>> > GC
>>> > 
>>> > On Mon, Aug 7, 2023 at 10:35 AM <[email protected] <mailto:[email protected]>> 
>>> > wrote:
>>> > Gregory, 
>>> > 
>>> > Thank you. I over last night, I was able to solve almost all the issues 
>>> > with calling into GNUStep's AppKit and Foundation. I've been able to set 
>>> > up buttons that respond to selectors, create objects at runtime and 
>>> > register them with the runtime. Right now, I am working on generalizing a 
>>> > sort of "Smart" version of obj_msgSend that allows me to not have to 
>>> > write a separate version of that handles each type parameters. As it is 
>>> > now, the only way I am getting it to work is to make a version of 
>>> > objc_msgSend that explicitly takes, for example, an NSRect, or id. 
>>> > 
>>> > This is probably because I just don't fully understand how pointers work 
>>> > in Swift. If anyone has any idea of how we can generalize the function, I 
>>> > would greatly appreciate it. Thanks!
>>> > 
>>> > Below is a screen shot of a working app written in Swift. The button does 
>>> > work and does open the other window. It's pretty cool. You can see the 
>>> > code on my GitHub. It's messy still.  
>>> > 
>>> > 
>>> > <Image 8-7-23 at 9.33 AM.jpeg>
>>> > 
>>> >> On Aug 6, 2023, at 7:59 PM, Gregory Casamento <[email protected] 
>>> >> <mailto:[email protected]>> wrote:
>>> >> 
>>> >> Hey, I just want you to know that this is VERY VERY cool!!!  Yours, GC
>>> >> 
>>> >> On Sun, Aug 6, 2023 at 12:05 PM <[email protected] <mailto:[email protected]>> 
>>> >> wrote:
>>> >> I have solved the NSWindow initializer issue. I didn't realize I was 
>>> >> passing Swift's Foundation.NSRect and not the C version. Sill haven't 
>>> >> solved the issues regarding adding new ObjC classes to the runtime at 
>>> >> runtime through Swift. Any ideas here would be appreciated.  
>>> >> 
>>> >> The image below is an GNUStep app written in Swift. The Menu is from the 
>>> >> GORM file from the Terminal (I had to start somewhere!)
>>> >> 
>>> >> <Screenshot 2023-08-06 at 10.54.06 AM.png>
>>> >> 
>>> >> 
>>> >>> On Aug 5, 2023, at 9:03 PM, [email protected] <mailto:[email protected]> 
>>> >>> wrote:
>>> >>> 
>>> >>> I just wanted to update everyone on my progress and solicit some help 
>>> >>> if possible.
>>> >>> 
>>> >>> State of my progress: 
>>> >>> I've had a lot of success patching into GNUStep's libobjc2 C runtime 
>>> >>> from within Swift. I've been able to create NSWindows through Swift, 
>>> >>> call methods, et cetera. You can see my progress here 
>>> >>> https://github.com/austintatiousness/GNUStepSwiftBridge . This assumes 
>>> >>> that you're running this from within OnFlapp's GNUStep Desktop. 
>>> >>> 
>>> >>> Solution to objcSendMessage: 
>>> >>> Because Swift doesn't allow variable argument parameters, I had to 
>>> >>> create various versions of objcSendMessage (e.g 
>>> >>> forSwift_objcSendMessage1, forSwift_objcSendMessage2, 
>>> >>> forSwift_objcSendMessage3) to accommodate various number of arguments. 
>>> >>> 
>>> >>> Problem 1: NSWindow initWithContentRect:styleMask:backing:defer
>>> >>> 
>>> >>> 1) I am having trouble with the NSWindow.initWith… functions. I am sure 
>>> >>> that it is because of the way that I am casting all the values from 
>>> >>> Swift into to the C implementation. Either I just don't understand how 
>>> >>> the casting between Swift and C works OR I am just using the wrong 
>>> >>> variables.  I include a C version of the NSRect struct in my project. 
>>> >>> 
>>> >>> let  nsWindowClass =  objc_getClass("NSWindow")
>>> >>> var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, 
>>> >>> sel_registerName("alloc"))
>>> >>> 
>>> >>> var styleMask: UInt64 = 1 + 2 + 4
>>> >>> var backingStoreType: UInt64 = 0
>>> >>> var deferr: UInt8 = 0
>>> >>> var rect = NSRect(x: 200, y: 200, width: 300, height: 300)
>>> >>> 
>>> >>> allocatedObject = forSwift_objcSendMessage4(&allocatedObject!.pointee, 
>>> >>> sel_registerName("initWithContentRect:styleMask:backing:defer:"), 
>>> >>> &rect, &styleMask, &backingStoreType, &deferr)
>>> >>> 
>>> >>> I've tried several times to change the various integer types from 
>>> >>> UInt64 to UInt8 to no avail. 
>>> >>> 
>>> >>> Problem 2: Registering new classes  with the runtime. 
>>> >>> This is the current state of the HelloWorld target: 
>>> >>> 
>>> >>> For reasons I cannot explain, I am able to allocate a new obj-c object 
>>> >>> with objc_allocateClassPair and then register it using 
>>> >>> objc_registerClassPair but when objc_getClass using the same class name 
>>> >>> that I registered, it returns nil.
>>> >>> 
>>> >>> Any help would be appreciated. I am currently unable to make progress 
>>> >>> on adding delegates with out being able to register new ObjC classes 
>>> >>> with the runtime. 
>>> >>> 
>>> >>> Thanks!
>>> >> 
>>> >> 
>>> >> 
>>> >> -- 
>>> >> Gregory Casamento
>>> >> GNUstep Lead Developer / OLC, Principal Consultant
>>> >> http://www.gnustep.org <http://www.gnustep.org/> - 
>>> >> http://heronsperch.blogspot.com <http://heronsperch.blogspot.com/>
>>> >> https://www.patreon.com/bePatron?u=352392 - Become a Patron
>>> >> https://www.openhub.net/languages/objective_c - OpenHub standings
>>> > 
>>> > 
>>> > 
>>> > -- 
>>> > Gregory Casamento
>>> > GNUstep Lead Developer / OLC, Principal Consultant
>>> > http://www.gnustep.org <http://www.gnustep.org/> - 
>>> > http://heronsperch.blogspot.com <http://heronsperch.blogspot.com/>
>>> > https://www.patreon.com/bePatron?u=352392 - Become a Patron
>>> > https://www.openhub.net/languages/objective_c - OpenHub standings
>>> 
>>> 
>> 
>> 
>> --
>> Gregory Casamento
>> GNUstep Lead Developer / OLC, Principal Consultant
>> http://www.gnustep.org <http://www.gnustep.org/> - 
>> http://heronsperch.blogspot.com <http://heronsperch.blogspot.com/>
>> https://www.patreon.com/bePatron?u=352392 - Become a Patron
>> https://www.openhub.net/languages/objective_c - OpenHub standings
> 

Reply via email to