I have the following Objective-C headers:
// Menu.h
#import <UIKit/UIKit.h>
#import "GameController.h"
#interface Menu : UIImageView {
GameController *gameController; // "Expected specifier-qualifier-list
// before GameController"
}
- (void)appear;
#end
and
// GameController.h
#import <UIKit/UIKit.h>
#import "Menu.h"
#interface GameController : UIView {
Menu *menu; // "Unknown type name 'Menu'"
}
- (void)startLevel0;
- (void)startLevel1;
- (void)startLevel2;
#end
When I try to build the project, Xcode (v4) yells at me, saying Expected specifier-qualifier-list before GameController and unknown type name 'Menu'. I'm sure that they are somehow related, but I have no idea how?
It's not good practice to have mutually-including header files. Instead of importing Menu.h, use the #class directive. Try removing #import "Menu.h" and adding #class Menu in its place. Ditto for Menu.h (remove GameController include, and add the #class directive)
You have a circular reference in your imports. The compiler builds a dependency tree from the import statements so when two Classes rely on each other it doesn't know how to compile one before the other.
Sadly, gcc kicks out a fairly nonsensical error statement when this happens "Expected specifier-qualifier-list". #yan is correct that you should use the #class directive. Check out this question for a solid explanation: #class vs. #import
Related
Project “app” gets build err: "Undefined symbol: run_mobile_session()"
Proj app includes ObjC class lib project hub_lib.
Proj hub_lib has folder with main.cpp file that has function "run_mobile_session()" that is undefined in app build
I build without error the hub_lib project and did ctrl-drag of its .h and .a from its Xcode folders pane to a folder within project app.
I dragged .h & .a from folder within app to folder pane of app. (ie. imported)
I selected target to be my provisioned iPhone.
Built app, got error.
I ran nm on and get this...
DOUGs-MacBook-Pro:mobile_sys_hub_lib dbell$ nm libmobile_sys_hub_lib.a | grep run_mobile_session
U __Z18run_mobile_sessionv
DOUGs-MacBook-Pro:mobile_sys_hub_lib
The U at the front of the line is "undefined". nm thinks you have a reference to the symbol but no implementation. – Phillip Mills
Doug: main.cpp seems to be getting compiled in the class lib: I put junk "zzzzzz" within run_mobile_session() and get build error.
THE CODE...
------------------------------------------- ObjC app project...
//app.h ...........................
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
// ViewController.mm ....................
#import <UIKit/UIKit.h>
#import "hub_lib.h"
#interface ViewController ()
#end
#implementation ViewController
. . .
- (IBAction)start_session:(id)sender
{
hub_lib* _lib = [hub_lib new];
NSLog(#"app: %d", [ _lib start_session]);
}
#end
--------------------------------------- lib project...
// hub_lib.h ....................
#import <Foundation/Foundation.h>
#interface hub_lib : NSObject
#end
// hub_lib.mm ......................................
#import "hub_lib.h"
#import <UIKit/UIKit.h>
#implementation hub_lib
extern void run_mobile_session(void);
. . .
-(int)start_session
{
run_mobile_session();
return 0;
}
#end
--------------------------------------- C++ folder within lib project...
// main.cpp .....................
#include <stdio.h>
void run_mobile_session(void);
. . .
void run_mobile_session(void)
{
. . .
}
Solution was to move the extern from hub_lib.mm to hub_lib.h and mod to be C++:
extern "C++" void run_mobile_session(void);
Thanks for solution, gnasher729.
All of a sudden, I'm getting "Expected unqualified-id" and "Type name declared as a reference to a reference" parsing issues from importing opencv2/opencv.hpp I tried relinking opencv3, upgraded from opencv 3 to 4 and restarted Xcode. How can this be resolved?
Used prebuilt opencv from here: https://opencv.org/releases/ and Xcode 10.2
See All Parsing Errors
Expected unqualified-id:
CODE - Removed everything and left with this, but it still has parsing errors.
-------
.mm
------
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
#import <Foundation/Foundation.h>
#import "OpenCVWrapper3.h"
#include <vector>
using namespace std;
#implementation OpenCVWrapper3
+ (NSString *) openCVVersionString
{
return [NSString stringWithFormat:#"OpenCV Version %s", CV_VERSION];
}
#end
----
.h
----
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface OpenCVWrapper3 : NSObject
+ (NSString *) openCVVersionString;
#end
Ok so... I don't have a clue what caused the error. I opened another ios project that uses opencv and it gave the same errors. Then I created a new project and added #include iostream, ostream and got the same error. So its was not isolated to opencv. So I deleted and reinstalled Xcode and now it works!! Bizarre!
So, I have a C++ project that I want to put into a framework that will act as a wrapper (written in Objective-C/C++) to the C++ code, so that I can later use this in a Swift or Objective-C project by simply adding the framework to the app.
What I have accomplished so far:
Created all the wrappers
Exposed the wrapper's public headers in the build phase
Added a run-script in the build phase to simply copy all the C++ headers (keeping their file directory structure) into the framework's directory, so that they are available to the app using the framework. The reason for me to do this and not just put them in the headers' field of the build phase is because there are a lot of files and folders and doing that would require me to change every header to #include "LocalHeader.h" rather than how it is currently written as #include "CppRootFolder/Subfolder/Header.h". Also I would rather not do this because I want to keep the C++ files unaltered.
The problem:
Everything seems to work well except that when building the actual app, xcode will error out saying it can't find the files inside the file structure. To illustrate what I mean, I have the following:
The umbrella file for the framework will #include "CppRootFolder/umbrella.h" (the c++ umbrella file)
In CppRootFolder/umbrella.h, I have several #include "CppRootFolder/Subfolder/Header.h"
Each one of the headers inside each subfolder include other headers referencing them from the root folder of the c++ code.
My take on this:
It seems clear to me that the issue is that the compiler needs to find the headers from the root folder of the c++ code. So, in the actual App, in build settings, I add a header search path to: $BUILT_PRODUCTS_DIR/FrameworkName.framework/Headers, which is where I copied all the headers with the script. However, the build fails and produces a lot of random errors not recognizing types that are already defined.
Any ideas on how I can get this to work?
Thanks
UPDATE (Logs):
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/Box2D.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:
#import "World.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:
#import "Box2D/Box2D.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:34:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:34:
#include "Box2D/Common/b2Settings.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Settings.h:153:8: error: must use 'struct' tag to refer to type 'b2Version'
extern b2Version b2_version;
^
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/Box2D.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D.h:17:
#import "World.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:9: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/World.h:10:
#import "Box2D/Box2D.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:35:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Box2D.h:35:
#include "Box2D/Common/b2Draw.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Draw.h:22:10: note: in file included from /Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Draw.h:22:
#include "Box2D/Common/b2Math.h"
^
/Users/luis/Library/Developer/Xcode/DerivedData/Project-dgathvjusrdgslfvqqcvkeqyjzcb/Build/Products/Debug-iphoneos/Box2D.framework/Headers/Box2D/Common/b2Math.h:28:31: error: unexpected type name 'int32': expected expression
int32 ix = *reinterpret_cast<int32*>(&x);
When you write a wrappers C++ should not be visible outside.
So #include "cppHedarFile.h" should not be accessible outside the wrapper, otherwise you will have an errors about using C++ in Objective C code.
So there should not be umbrella header file for C++ headers.
Please provide technical details: copy paste error message you are seeing. Your interpretation of error can be misleading.
You didn't paste everything but this line:
/Box2D.framework/Headers/Box2D/Common/b2Math.h:28:31: error: unexpected type name 'int32': expected expression
int32 ix = *reinterpret_cast<int32*>(&x);
Give me a hind that I'm right.
Most probably you are including C++ headers from Objective C file *.m.
For such file C++ standard headers are not reachable that is why type int32 is not recognized.
Like I've wrote at begging. When you are writing a Objective C wrapper around C++, includes of C++ headers from public headers are forbidden.
You can do it only form *.mm file for from internal headers which are only used by *.mm.
This way wrappers are doing their job and handing C++ from user of wrapper.
Example
Public header KXSomeClass.h:
#interface KXSomeClass : NSObject
#property (nonatomic, readonly) BOOL allowed;
- (NSUInteger)someAction:(NSString *)s;
#end
Private header KXSomeClass+Internal.h
// this header is used only by wrappers
#import "KXSomeClass.h"
#include <memory>
#interface KXSomeClass ()
- (instancetype)initWithNativeSomeClass:(const std::shared_ptr<SomeClass>&)nativeObject;
#end
Implementation KXSomeClass.mm
#import "KXSomeClass+Internal.h"
#interface KXSomeClass ()
#property (assign, nonatomic) std::shared_ptr<SomeClass> native;
#end
#import "KXSomeClass+Internal.h"
#include "cpp/SomeClass.h"
#implementation CSCapability
- (instancetype)initWithNativeSomeClass:(const std::shared_ptr<SomeClass>&)nativeObject
{
if (self = [super init]) {
_native = nativeObject;
}
return self;
}
- (NSUInteger)someAction:(NSString *)s
{
return _native->SomeAction(s.UTF8String);
}
- (BOOL)allowed
{
return _native->Allowed();
}
#end
I am trying to use one of my Objective-C class from another target, in my Swift class inside extension target.
I created the <Project-Name>-Bridging-Header.h and included that objective-c file, but the build is not compiling because of build error in "Cryptor.h" and <CommonCrypto/CommonDigest.h>. I believe this has to do something with CommonCrypto framework.
This is how my Bridging-Header.h looks:
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import <GooglePlus/GooglePlus.h>
#import <Security/Security.h>
#import <CommonCrypto/CommonCrypto.h>
#import <CommonCrypto/CommonDigest.h>
I guess this is due to Common Crypto library. Has anybody encountered the same issue and solved it?
EDIT:
Specifically, i am getting build error - "Missing #end" in CommonDigest.h and because CommonDigest.h is not getting build hence the error in Cryptor.h.
I don't know if it will fix your problem, but the bridge-header is sometimes a bit buggy. At least it was the case for me.
Try to edit your header and import your files like that:
#import "FacebookSDK.h"
#import "GooglePlus.h"
#import "Security.h"
#import "CommonCrypto.h"
#import "CommonDigest.h"
I have removed the UIKit-header, because you don't really need it, because swift has it's own UIKit.
/Users/uuu/Projects/osx/Menu.mm:28:
error: attempting to use the forward class 'NSObject' as superclass
of 'MenuProvider' #interface MenuProvider : NSObject
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
in code:
#interface MenuProvider : NSObject
- (void)share:(bool)force userData:(NSString*)data;
#end
Qt Creator (qt 5.3), clang-600.0.51, osx
Add #import <Foundation/Foundation.h> above that #interface definition.