I have a header file that is included by *.c and by *.m sources. When a C source includes the file, I'd like to skip some lines that contain Objective C stuff. Thus, I was wondering if gcc has a builtin compiler define that is active whenever it is compiling an Objective C file, something similar to the __cplusplus define that indicates that the compiler is currently compiling a C++ source. Is there an Objective C equivalent?
Of course, I could just #define my own preprocessor symbol but I'd like to know whether gcc already has an inbuilt definition for this.
To answer my own question, gcc defines the __OBJC__ macro whenever it is compiling an Objective C source.
I just changed my .m files to .mm and use C++. Is there a way to do the same with Swift?
The confusion may come from the assumption that merely changing a file extension from .m to .mm is all you need to bridge the languages, when, in reality, it does nothing of that sort. It is not the .mm that causes friction with .cpp, it is the .h header which must positively not be a C++ header.
Same project: Yes.
In the same project, you can happily mix C, C++, Objective-C, Objective C++, Swift, and even Assembly.
...Bridging-Header.h: you expose C, Objective-C and Objective-C++ to Swift using this bridge
<ProductModuleName>-Swift.h: exposes automatically your Swift classes marked with #objc to Objective-C
.h: this is the tricky part, since they are ambiguously used for all flavors of C, ++ or not, Objective or not. When a .h does not contain a single C++ keyword, like class, it can be added to the ...Bridging-Header.h, and will expose whatever function the corresponding .c or .cpp functionalities it declares. Otherwise, that header must be wrapped in either a pure C or Objective-C API.
Same file: No.
In the same file, you can't mix all 5. In the same source file:
.swift: you can't mix Swift with anything
.m: you can mix Objective-C with C. (#Vinzzz)
.mm: you can mix Objective-C with C++. This bridge is Objective-C++. (#Vinzzz).
.c: pure C
.cpp: you can mix C++ & Assembly (#Vality)
.h: ubiquitous and ambiguous C, C++, Objective-C or Objective-C++, so the answer is it depends.
References
Invoke Assembly from C++ (Brett Hale)
Invoke Swift from Objective-C (Svitlana)
Invoke C, C++, Obj-C, Obj-C++ from Swift (SwiftArchitect, self)
To download a full iOS 9, Xcode 7 project, search for SO-32541268 in Swift Recipes.
No. When you switch from .m to .mm you are actually switching from Objective-C to a different language (which has many subtle differences) called Objective-C++. So you're not really using C++; you're using Objective-C++ which accepts most C++ as input (in the same way that C++ accepts most but not all C as input). When I say it's not quite C++, consider a C++ file that includes a variable named nil (which is legal C++) and then try to compile that as Objective-C++.
Swift doesn't have the same relationship. It is not a superset of C or C++, and you can't directly use either in a .swift file.
"Using Swift with Cocoa and Objective-C" also tells us:
You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.
I wrote a simple Xcode 6 project that show how to mix C++, Objective C and Swift code:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
In particular the example call an Objective C and a C++ function from the Swift.
The key is to create a shared header Project-Bridging-Header.h and put the Objective C headers there.
Please download the project as a complete example.
You can also skip the Objective-C file in between. Just add a C header file with a .cpp source file. Have only C declarations in the header file and include any C++ code in the source file. Then include the C header file in the **-Bridging-Header.h.
The following example returns a pointer to a C++ object (struct Foo) so Swift can store in a COpaquePointer instead of having struct Foo defined in the global space.
Foo.h file (seen by Swift - included in the bridging file)
#ifndef FOO_H
#define FOO_H
// Strictly C code here.
// 'struct Foo' is opaque (the compiler has no info about it except that
// it's a struct we store addresses (pointers) to it.
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
#endif
Inside source file Foo.cpp (not seen by Swift):
extern "C"
{
#include "Foo.h"
}
#include <vector>
using namespace std;
// C++ code is fine here. Can add methods, constructors, destructors, C++ data members, etc.
struct Foo
{
vector<int> data;
};
struct Foo* foo_create()
{
return new Foo;
}
void foo_destroy(struct Foo* foo)
{
delete foo;
}
I have just made a little example project using Swift, Objective-C and C++. It's a demo of how to use OpenCV stitching in iOS. The OpenCV API is C++ so we can't talk to it directly from Swift. I use a small wrapper class who's implementation file is Objective-C++. The Header file is clean Objective-C, so Swift can talk to this directly. You have to take care not to indirectly import any C++-ish files into the the headers that Swift interacts with.
The project is here: https://github.com/foundry/OpenCVSwiftStitch
Here's my attempt at a clang tool to automate C++/swift communication. You can instanciate C++ classes from swift, inherit from C++ class and even override virtual methods in swift.
It will parse the C++ class you want to export to swift and generate the Objective-C/Objective-C++ bridge automatically.
https://github.com/sandym/swiftpp
Swift is not directly compatible with C++. You can work around the issue by wrapping your C++ code with Objective-C, and using the Objective C wrapper in Swift.
I also have a demo program for swift combining opencv.
You can download it from https://github.com/russj/swift_opencv3_demo.
More information about the demo http://flopalm.com/opencv-with-swift/.
No, not in a single file.
However, you may use C++ in Swift Projects without needing a static library or framework. Like others have said, the key is to make an Objective-C bridging header that #includes C-compatible C++ headers that are marked as C compatible with the extern "C" {} trick.
Video tutorial: https://www.youtube.com/watch?v=0x6JbiphNS4
Other answers are slightly inaccurate. You can actually mix both Swift and [Objective-]C[++] in the same file, though not quite the way you would expect.
This file (c.swift) compiles to a valid executable with both swiftc c.swift and clang -x objective-c c.swift
/* /* */
#if 0
// */
import Foundation
print("Hello from Swift!")
/* /* */
#endif
#include <stdio.h>
int main()
{
puts("Hello from C!");
return 0;
}
// */
One trick (of many) is that
You need a separate header for your bridging obj-c++ file...
You can't just throw #interface and #implementation in the same .mm file as one often does normally.
So in your bridging header file you have
#import "Linkage.hpp"
Linkage.hpp has the #interface for Linkage and Linkage.mm has the #implementation for .mm
And then
...you actually don't #include "yourCpp.hpp" in Linkage.hpp.
You only put #include "yourCpp.hpp" in the Linkage.mm file, not in the Linkage.hpp file.
In many online examples/tutorials, the writer simply puts the #interface and #implementation in the same .mm file, as one often does.
That will work in very simple cpp bridging examples, but,
The problem is:
if your yourCpp.hpp has any c++ features at all which it surely will (like, the first line #include <something>), then the process will fail.
But if you just don't have the #include "yourCpp.hpp" in the Linkage header file (it's fine to have it in the .mm file, obviously you'll need to) - it works.
Again this is unfortunately just one tip in the whole process.
In case this is helpful to anyone, I also have a brief tutorial on calling a simple C++ static library from a trivial Swift command line utility. This is a really bare-bones proof of concept piece of code.
No Objective-C involved, just Swift and C++. Code in a C++ library is called by a C++ wrapper that implements a function with extern "C" linkage. That function is then referenced in the bridging header and called from Swift.
See http://www.swiftprogrammer.info/swift_call_cpp.html
I am providing a link to SE-0038 in the official resource, described as
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
The status as of today is that this is the feature request which has been accepted but not yet scheduled.
This link is intended to steer anyone looking for this feature in the right direction
I was reading the clang documentation on reference counting, which says that “ By default in Objective-C, ARC is not exception-safe”. It proceeds to say:
A program may be compiled with the option -fobjc-arc-exceptions in order to enable these, or with the option -fno-objc-arc-exceptions to explicitly disable them, with the last such argument “winning”.
In Objective-C++, -fobjc-arc-exceptions is enabled by default.
I was intrigued. Are there any other compiler options whose default change between Objective-C and Objective-C++?
Complementary question: what is difference between compiling purely Objective-C code with clang in Objective-C++ mode (*.mm files) rather than in Objective-C mode only (*.m)?
Best way is to log what clang will output from all those c language
here's some of what i have got from a obj-c++ compilation
clang++ -fobjc-arc main.mm -v
/.../
-fblocks
-fobjc-runtime=macosx-10.7.0
-fobjc-dispatch-method=mixed
-fobjc-default-synthesize-properties
-fobjc-arc
-fobjc-arc-cxxlib=libstdc++
-fobjc-arc-exceptions
-fobjc-exceptions
-fcxx-exceptions
-fexceptions
-fdiagnostics-show-option
-fcolor-diagnostics
/.../
As you can see those output can vary depending from where you compile it. But some of them are constants.
You should try on different c families files in order to determine what the default option are for these respective.
Hope it will help you.
To answer the second part of your question: If you compile files in Objective-C mode rather than Objective-C++ mode, you get better support from the Static Analyzer [1]. I believe the compiler will also generate more accurate warnings in general (without using the Static Analyzer), but I cannot find/remember the source of that information.
My problem is a little complex:
Library:
I have a library written in C and C++. It compiles perfecly in XCode with Apple LLVM.
The work of this library itself is done by the C code while the C++ part is just a C++ interface because I prefer C++. In theory I need to use only C++ to comunicate with it.
The application:
I have an application in Objective-C that uses the library above. Of couse, as the communication with my library is done via C++ I need to have a .mm file in order to call my library from "Objective-C++".
During the compilation... several issued of "C" languages happen:
error: non-const static data member must be initialized out of line
error: statement expression not allowed at file scope
etc...
It only happens with Objective-C++
Objective-C++ (app) -> C++ headers (lib) -> C headers (lib, with extern "C") -> NOT OK!!! WHY?
If I make another C++ application for test of library, it goes ok
C++ (app) -> C++ (lib) -> C header (lib, with extern "C") -> OK
Detail: I am always using the Apple LLVM compiler here
The question:
How do I compile C code from C++ from Objective-C++ code? Why it's different than compile from a regular C++ code?
Don't forget to do
#ifdef __cplusplus
extern "C" {
#endif
<Some C method declaration>
#ifdef __cplusplus
}
#endif
in your header files that contain C method declarations.
After a long period of tries and Google I finally could figure out.
Before I call my C headers, I should undefine MAX and MIN macros. For some reason they were previous defined. The compiler doesn't show the error with precision. That's why it was difficult. The C framework I am using has it's own declaration of MAX and MIN macros...
Another very interesting thing that might be useful for others is that before we need to do the same thing: undefine max and min (lower case) if we are using some C framework that implements it's own max and min.
It solved both problems.
Compiling my project on new xcode4 using llvm 2.0 compiler I get a strange error coming from standard <sqlite3.h> header. Problem is with the following line:
//<sqlite3.h>
typedef struct sqlite3 sqlite3;
Error message:
In file included from /Projects/trunk/MyProj/Classes/StatsProvider.m:14:
Elaborated type refers to a non-tag type in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/include/sqlite3.h
Using GCC 4.2 project compiles with no problem
How can I fix that error?
My guess: you are compiling sqlite as C++ code, whereas you should compile it as plain C code. class/struct keywords implicitly introduce a typedef in C++, but not so in C.
I interpret the error message as the compiler complaining about using struct sqlite3 when it hasn't seen a struct declaration with that name. Struct names are in a special "tag-space".
My next guess is that the new compiler is stricter than the old one, and has found a bug.