[swift-users] Referencing Swift Functions from the Objective-C Runtime

Brian Gesiak modocache at gmail.com
Mon Nov 21 10:06:03 CST 2016


I'm curious: what are you hoping to accomplish with corelibs-xctest? If we
can help you by modifying corelibs-xctest itself, that could be another
option here. :)

- Brian Gesiak


On Mon, Nov 21, 2016 at 10:46 AM, Jeff Kelley via swift-users <
swift-users at swift.org> wrote:

> The type comes from XCTest. I’m trying to enumerate Objective-C methods in
> order to use them with XCTest in the open-source Swift version of XCTest,
> which needs the tests to be supplied as this type:
>
> /// This is a compound type used by `XCTMain` to represent tests to run. It combines an
> /// `XCTestCase` subclass type with the list of test case methods to invoke on the class.
> /// This type is intended to be produced by the `testCase` helper function.
> /// - seealso: `testCase`
> /// - seealso: `XCTMain`
> public typealias XCTestCaseEntry = (testCaseClass: XCTestCase.Type, allTests: [(String, (XCTestCase) throws -> Void)])
>
>
>
>
> Jeff Kelley
>
> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
> jeffkelley.org
>
> On Nov 21, 2016, at 1:13 AM, Jacob Bandes-Storch <jtbandes at gmail.com>
> wrote:
>
> "throws" is the part that's not representable in Obj-C. Why are you using
> it? If you're interacting with method_getImplementation, you need to think
> like the Obj-C runtime.
>
> https://developer.apple.com/library/content/documentation/
> Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html#//
> apple_ref/doc/uid/TP40008048-CH104-SW1
>
> This works:
>
>     typealias DescriptionMethod = @convention(c) (NSObject, Selector) ->
> NSString
>
>     let fn = unsafeBitCast(method_getImplementation(class_
> getInstanceMethod(NSObject.self, "description")), DescriptionMethod.self)
>
>     fn(NSObject(), "description") as String
>
>
> Jacob
>
> On Sun, Nov 20, 2016 at 9:41 PM, Jeff Kelley <slaunchaman at gmail.com>
> wrote:
>
>> Still trying on this (copied the code directly, Foo is actually
>> XCTestCase):
>>
>> typealias TestMethod = @convention(c) (XCTestCase) throws -> Void
>>
>> This seagulls the compiler with “error: '(XCTestCase) throws -> Void' is
>> not representable in Objective-C, so it cannot be used with '@convention(c)
>> ’”. I’m trying to use it here:
>>
>> let testMethod: IMP = method_getImplementation(method)
>>
>> let test: TestMethod = unsafeBitCast(testMethod,
>>                                      to: TestMethod.self)
>>
>> testMethods.append((methodName as String, test))
>>
>> If I try to put the type directly in the call to unsafeBitCast(), the
>> compiler gives me an error:
>>
>> Attribute can only be applied to types, not declarations
>>
>> Thanks for your suggestions! I hadn’t seen @convention() before.
>>
>>
>> Jeff Kelley
>>
>> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
>> jeffkelley.org
>>
>> On Nov 21, 2016, at 12:08 AM, Jacob Bandes-Storch <jtbandes at gmail.com>
>> wrote:
>>
>> For a function such as bar() above, the type you want to cast the IMP to
>> would probably be "@convention(c) (Foo, Selector) -> ()".
>>
>> On Sun, Nov 20, 2016 at 9:05 PM, Jeff Kelley <slaunchaman at gmail.com>
>> wrote:
>>
>>> Thanks Jacob! I tried using unsafeBitCast, but it fails with the
>>> following: “fatal error: can't unsafeBitCast between types of different
>>> sizes”. I considered wrapping every call in a closure that calls
>>> objc_msgSend(), but alas, that’s not exposed to Swift. I have another
>>> approach in mind, so I’ll try that next.
>>>
>>>
>>> Jeff Kelley
>>>
>>> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan>
>>>  | jeffkelley.org
>>>
>>> On Nov 19, 2016, at 1:58 AM, Jacob Bandes-Storch <jtbandes at gmail.com>
>>> wrote:
>>>
>>> I imagine unsafeBitCast would be the way to go here. But are you
>>> assuming that all of the instance methods have type "(Foo) throws -> Void"
>>> ? Or do you somehow want to dynamically use the type information?
>>>
>>> Jacob
>>>
>>> On Fri, Nov 18, 2016 at 10:37 PM, Jeff Kelley via swift-users <
>>> swift-users at swift.org> wrote:
>>>
>>>> Hello,
>>>>
>>>> I’m trying to enumerate the methods of a class in Swift using the
>>>> Objective-C runtime. Everything is working fine so far, except for the very
>>>> last step. Suppose I have a Swift class like this:
>>>>
>>>> class Foo: SomeSuperclass {
>>>>
>>>>     @objc func bar() {
>>>>         print("Hello, World!")
>>>>     }
>>>>
>>>> }
>>>>
>>>> Using the Objective-C runtime methods, I can get the method with
>>>> class_copyMethodList and then get to the method’s implementation using
>>>> method_getImplementation. However, what I need to do next is to stick
>>>> this into a tuple that looks like this:
>>>>
>>>> typealias FooEntry = (fooClass: SomeSuperclass.Type, methods: [(String,
>>>> (Foo) throws -> Void)])
>>>>
>>>> For now, the workaround is to make a static variable that returns all
>>>> of the entries:
>>>>
>>>>     static var allEntries = {
>>>>         return [
>>>>             ("bar", bar),
>>>>         ]
>>>>     }
>>>>
>>>> Is there any way to go from the raw IMP that I get back from the
>>>> runtime to the Swift type so I can construct this list dynamically?
>>>>
>>>>
>>>> Jeff Kelley
>>>>
>>>> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan>
>>>>  | jeffkelley.org
>>>>
>>>>
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>
>>>>
>>>
>>>
>>
>>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161121/bed8aa6d/attachment.html>


More information about the swift-users mailing list