I created a simple external using the LiveCode iOS externals SDK. The test.lcidl file is as follows:
external test
function testMyExternal
return boolean
The test.mm file is as follows:
bool testMyExternal(void) {
return true;
}
The test.ios file is the default Foundation framework.
This is about as simple as it gets but it won't compile... why not?
This question was asked on a LiveCode listserve and I'm asking and answering here because the answer will be useful for others.
There are a few problems here:
First is the ios file which specifies frameworks and libraries to compile the external against includes Foundation framework yet the use objc-objects clause is not specified in the .lcidl file. If you don't want to use objective c objects then remove the foundation framework from the .ios file.
Second is the file is a .mm which is Objective-C++ and the use c++-naming clause is not specified. If you don't want C++ you can change the .mm to .c for C or .m for Objective-C.
More detail can be found in section 6.3 of the documentation
Monte managed to answer his own question but in this case the external is a .mm file which means its obj-c++. This means you need to add use c++-naming in the lcidl file
otherwise the glue code that's generated will look for C-style (unmangled) names
(C++ 'mangles' names of functions to include the typing information so that they can be overloaded)
Related
I'm a C++/Python developer recently starting to learn Swift and trying out iOS programming. I have a machine learning model that I've converted into Apple's Core ML format, and have successfully been able to use it in an iOS app in Swift, such as initializing a model with:
var model = MODELNAME()
Now, I have some existing C++ codes that I want to integrate into the app. A simple way to do this is to create a bridging .mm file in Obj-C, and wrapping the C++ code in Obj-c. By itself, the Obj-C wrapper and the C++ codes work without a problem with Swift, and I've been able to use the C++ functions in the iOS Swift app.
However, I noticed a rather confusing bug when I tried to load the Core ML model in the mixed Swift/Objective-C project. If I add .m source codes - even empty files - into the project (which automatically creates a bridging file Project-Bridging-Header.h), the compiler would report an error of "Use of unresolved identifier MODELNAME" for the Core ML model in the Swift code. On a Mac, simpling adding one .m file will cause the project to fail to compile. On iOS, adding one .m file is okay, but adding two .m files causes the same error to appear. Note that, only the .m (and by extension .mm, .cpp) source files affect the compiler, and header files do not.
I'm rather confused with this error...(since somehow, the sheer number of Obj-C sources in the XCode "compiled sources" list - not their contents, affects whether the Core ML model can be compiled). My guess is this might have something to do with how XCode automatically generates a header MODELNAME.h for Core ML models (which usually do not need to be explicitly imported in the code) and this somehow interferes with Obj-C bridging headers Project-Briding-Header.h and the Obj-C source codes.
May I ask if anyone has met similar problems or might have an idea of the reason behind this phenomenon? Thanks!
Screenshot of the project files
I want to use the openCV2 framework in my iOS app, however, I am more comfortable with swift. I can read and understand obj-c well enough to understand the framework and write the methods I need from it in a bridging header, but I'm not comfortable writing the whole app in obj-C. Unfortunately, there are some data types, (cv::Mat, cv::MserManager, etc) that I will need to use in my datamodel, or possibly elsewhere. Is there a way to include datatypes in my bridging header so that I can work with them in swift?
You cannot use C++ types in code called from Swift. However, you can use them in Objective-C++ files, the ones that have the .mm extension. You can mix Objective-C and C++ code in Objective-C++, and can expose Objective-C methods that don't reference C++ in their declarations to Swift via the bridging wrapper. These functions can still use C++ in their implementations, which are not visible in Swift via the bridging header.
You also need to be careful about the language linkage (remember extern "C"?).
Here are some answers that provide examples:
1) Video processing with OpenCV in IOS Swift project
2) Include C++ header file in Swift
3) How to access Swift-objects from a c++ class?
Unfortunately, you cannot bridge C++ and Objective-C++ directly into Swift. On the bright side, you can still work with the openCV2 framework in your app, but you'll need to write C or Objective-C wrappers for your types as described in a related question here: Can I mix Swift with C++? Like the Objective - C .mm files
Can we create iOS app with swift and obj c both.My half app is made using OBJ-C and just want to improve apps performance so is that possible to use swift in between
Yes you can.
You have to add objc header #imports in the <module name>-Bridging-Header.h that you want to make available in swift, and you can use swift code from objc by importing the <module name>-Swift.h file in your objc code.
Note that the latter header file is automatically generated when building, and it is not visible in the project navigator - but you can open it by cmd+click-ing its name in an existing #import. Also to note that if compilation fails, most likely the file will not be generated.
Last, I highly recommend that you avoid circular references between objc and swift - for instance, creating a SwiftClass, inherited from BaseObjcClass, and using SwiftClass from objc - I've experienced that it doesn't work (compilation errors), and I am not aware of any workaround
Yes, you can. You just need to follow this:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
Apple’s intention to replace the Objective-C language using Swift, it is not practical in the short term simply due to the fact that developers are deeply entrenched in Objective-C. Rather than force Swift down the developer’s throat, Apple has made it easy to allow Objective-C to interoperate with Swift.
http://mobiforge.com/design-development/using-objective-c-and-swift-together-ios-apps
Dec 2018 - I found this useful YouTube video that helps explain what files you need to add and how to make the connections.
YouTube - How to use Swift and Objective-C in the same project
Background
I'm new to iOS development and playing with Swift for the sake of learning. As a small challenge, I'm trying to get the SSID of network to which a device is currently connected.
This is well-covered ground on Stack using Objective-C: iPhone get SSID without private library, for example ... but the Objective-C / Swift dance is causing me some conceptual challenges.
Specifically, the suggested solution (discussed in the above-linked post) is to call the function CNCopyCurrentNetworkInfo() -- but, according to Apple's documentation, this function is not available in Swift.
So far
I've included (I think correctly) SystemConfiguration.framework by adding it to the Linked Frameworks and Libraries of the project. I've also brought it into the View Controller using import SystemConfiguration.
Questions
Do I need to also use import SystemConfiguration, or is that already done due to including the framework with my project?
Is there another / better way to include the SystemConfiguration library?
The big one: How, once the required library is imported, do you call the Objective-C function from the library?
Thank you!
I know this is not directly answering your question, but it's an answer to your problem.
You can do everything in swift in your case.
After importing the library,
import SystemConfiguration.CaptiveNetwork
You can immediately call:
CNCopySupportedInterfaces()
and it will work.
Confirmed in Xcode 6.3.2.
Apple's interoperability book (from Understanding the Swift Import Process):
Any Objective-C framework (or C library) that’s accessible as a module
can be imported directly into Swift. This includes all of the
Objective-C system frameworks—such as Foundation, UIKit, and
SpriteKit—as well as common C libraries supplied with the system.
Regarding your specific questions:
The opposite is the case: you do not need to manually include Apple's frameworks. Xcode will automatically make them available to you given a valid import statement (such as import SystemConfiguration in your case), even – or rather: especially – in a playground!
ditto...
Given the above import statement, SystemConfiguration is indeed imported since you can call its functions (e.g. SCCopyLastError() // --> __NSCFError) and access its constants (e.g. kCFErrorDomainSystemConfiguration // --> com.apple.SystemConfiguration). Unfortunately, CaptiveNetwork does not seem to be imported with it (e.g. CNCopySupportedInterfaces() // --> Use of unresolved identifier).
You should be able, however, to use this framework on the Objective C side and simply call your own wrapper functions from Swift. You just need to remember to include them among the imports listed in your bridging header (see Swift and Objective-C in the Same Project for more about bridging headers).
I had built PJSIP 2.7.1 and was integrating it for an iOS app written in Swift. Everything worked so I believed it was built the right way, all libs and headers were in the right place too, until one day I was trying to call lib functions from an external thread so I had to register this thread by using pj_thread_register() and declared a pj_thread_t type variable, the compiler started to complain about that the type pj_thread_t was undeclared.
I found the pj_thread_t was declared in pj/types.h and was defined in pj/os_core_linux_kernel.c. The types.h was already included in the header search path and I supposed it should work. I guess I must have missed something here.
I met the same problem in my Swift project. My solution is create a kind of wrapper file in ObjC. Swift and ObjC works with memory in different ways. This is why my wrapper works good. Now I can call pj_thread_t inside my wrapper file.
pjsip (C) --> MyWrapper file (ObjC) --> myProject' files (Swift)
MyProject-Bridging-Header.h file contain only one row:
#import "MyWrapper.h"