swiftobjective-c++

Invoking a static swift function of an extended class from ObjC++


I have a swift class containing a lot of methods. I've split it into multiple classes using the extension keyword.

Taking an example,

@objc
class SwiftModule : NSObject {
    
    @objc
    static func Method1 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {                
        // Does something
    }

    @objc
    static func Method2 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {   
        // Does something             
    }
}

@objc
extension SwiftModule {

    @objc
    static func Method3 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {           
        // Does something
    }
}

Now, I have to invoke this method from C++ using the ObjC++ wrapper. I have the following in a .mm file,

// Include the generated swift interface header to invoke swift methods from C++
#include    "GeneratedSwiftInterfaceHeader.hpp"

bool CppModule::InvokeMethod1 () {

    NSString *  string;

    [SwiftModule Method1:&string];

    if ([string length] == 0)
        return false;

    // Do something with string

    return true;
}

bool CppModule::InvokeMethod2 () {

    NSString *  string;

    [SwiftModule Method2:&string];

    if ([string length] == 0)
        return false;

    // Do something with string

    return true;
}

bool CppModule::InvokeMethod3 () {

    NSString *  string;

    [SwiftModule Method3:&string];

    if ([string length] == 0)
        return false;

    // Do something with string

    return true;
}

I'm able to invoke Method1 and Method2. But Method3 failed with the following error

ibc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SwiftModule Method3:]: unrecognized selector sent to class 0x107343398'
terminating with uncaught exception of type NSException
(lldb) 

This means that Method3 is not recognised as part of SwiftModule class, right? Why? Where did I go wrong?

I have seen a few posts (this and this) which showcase a similar problem, but it still doesn't work.

I'm using swift 5.0 and Xcode 13.4.


Solution

  • When discussing the problem in details in the comments section, it turned out that the Objective-C interfaces generated were part of a static library which the final project is linked against.

    There is a known issue with Objective-C categories inside of static libraries, where the categories methods implementation are not "glued" to their symbolic names by linker. In order to get it round you pass -ObjC flag to the linker in the application (not library) target build settings. It will make the linker to load all symbols of static libraries found in both Objective-C classes and categories: enter image description here