1

I'm having issues with calling swift methods & using swift classes inside objective-c++ code. I have following class in swift:

@objc class MetalRenderer : NSObject
{
    // implementation
    ...
}

Then I have header file in which I have forward declaration @class MetalRenderer; and in source (.mm) file I include "Project-Swift.h" file and instantiate swift class and call methods on that class, no problem. However, when I try to make my class conform to MTKViewDelegate protocol code doesn't work anymore. This is what I have in swift:

@objc class MetalRenderer : NSObject, MTKViewDelegate
{
    // implementation
    ...

    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
        //...
    }

    func draw(in view: MTKView) {
        //...
    }
}

Same header file & including same "Project-Swift.h" file in .mm. However now the .mm fails to compile, with

No type or protocol named 'MTKViewDelegate'

I'm C++ developer with little understanding of Obj-C/Obj-C++/Swift. I understand that there is problem in "-Swift.h" file, which doesn't know the MTKViewDelegate protocol. The same file includes both Metal and MetalKit frameworks which has definition of that protocols. Those imports are however surrounded by preprocessor guards for some modules. I've found some posts about people having similar issues and the proposed solutions are to get rid of some include cyclic references, which are not present in my case (I guess) or to use swift code in Objective-C and not Objective-C++. I wrapped my code in Objective-C class and it works again, but I don't understand why I can't call it directly from Objective-C++, because the code is basically the same & I'm not satisfied with that I have to provide unnecessary indirection of wrapping that code. My question is, is it possible to directly call swift class methods from objective-c++, why it doesn't work (probably because of those modules, but what are they, how they work?)?

6
  • 1
    Objective-C++ has quite a few restrictions to be compatible with C++. As a result it's not as well tested by Apple as they don't really encourage it. It really exists to wrap libraries that were legacy. I would highly suggest just going pure swift if possible. It's easier to call a C api from swift than an objective-C++ api. Commented Jun 4, 2019 at 14:36
  • In my case it's exactly the opposite. Most of my codebase is shared on many plaforms, therefore it's written in C++ and I have low level platform specific stuff implemented in Obj-C/C++. I wanted to learn swift so I decided to code some platform specific stuff in Swift and avoid Obj-C as much as possible, but it seems that's still not a viable option, and it might be still better to go for obj-c/c++ only. Sadly. Commented Jun 4, 2019 at 14:42
  • 1
    Objective-C++ can't use @import. You need add #import somewhere, may be in .pch Commented Jun 4, 2019 at 14:49
  • @mezo so I would suggest either exporting a procedural API that is C compatible or wrapping the C++ and then importing that to swift. But Swift to objective-C++ is possible as far as I'm aware but not encouraged. Commented Jun 4, 2019 at 14:58
  • @Cy-4AH I've tried to import MetalKit using #import but that didn't help Commented Jun 4, 2019 at 15:25

3 Answers 3

0

Those imports are however surrounded by preprocessor guards for some modules.

Looks like you have already answered yours question: MetalKit framework isn't included.

You can just declare MTKViewDelegate protocol prototype if importing whole framework causes troubles

Sign up to request clarification or add additional context in comments.

2 Comments

Tried that too, did not work. And also, I'm not sure about Objective-C/C++ but forward declaration of MTKViewDelegate probably isn't enough as my class is subclassed on it (or in terms of obj-c, conforms to the protocol). In C++ it's definitely not possible to forward declare class and then define class derived from that class.
Then you are doing something wrong. Yours class is derived from NSObject, not from MTKViewDelegate. Subclassing and conforming is two big different things, not just terms.
0

Import MetalKit at the top of your .mm file:

#import <MetalKit/MetalKit.h>
#import "Project-Swift.h"

I was having the exact same problem and this fixed it for me.

Comments

0

I added the #import in the .pch file and it worked.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.