Any of you guys had errors when building your iOS project after updating to the new Google Cast 2.6.0 framework?
I get the following error:
Default initialisation of an object of const type ‘const NSInteger’ (aka ‘const int’).
at the following lines in class GCKDevice:
/** Device capability flag for video out. */
GCK_EXPORT const NSInteger kGCKDeviceCapabilityVideoOut;
/** Device capability flag for video in. */
GCK_EXPORT const NSInteger kGCKDeviceCapabilityVideoIn;
/** Device capability flag for audio out. */
GCK_EXPORT const NSInteger kGCKDeviceCapabilityAudioOut;
/** Device capability flag for audio in. */
GCK_EXPORT const NSInteger kGCKDeviceCapabilityAudioIn;
There is a bug in this version of the SDK for files compiled under Objective-C++. If you import the classes from a .mm file, there is a missing extern which will trigger a problem. As a workaround, if you can move you code to a regular .m file you should be OK (and you should be able to call out to that as long as you don't expose the GCK headers to the mm).
For me it helped to switch the "No Common Blocks" compiler setting to NO:
It pretty much seems to make sense, this setting defines how duplicate variable definitions are handled by the compiler. It is explained here: What is GCC_NO_COMMON_BLOCKS used for?
Related
OBJ-C ONLY...
That is,
An ObjC app imports ObjC static lib A.
Static lib A imports static lib B.
Static lib A has functions that call functions within lib B.
The app only calls functions in lib A and does not call functions in lib B.
Can I assume that lib A or B can be either Obj-C or Swift?
IE. Can an ObjC app import an ObjC-or-Swift static lib A that itself imports a second ObjC-or-Swift static lib B? (yes, 4 use case permutations)
the git repository https://github.com/CombineCppSwiftObjcInStaticLib i created for you is showing this..
your initial #objc func run_central() in BLE_central.swift is exposed, which triggers the precompiler to generate objc compatible headers (bridge) which then again makes it possible to call the function from a method inside .mm(objc++) or .m(objc) when this generated header is imported.
In fact Hub_lib inside the repo is a static ObjC++ lib mixed with Swift. It would work the other way around also. The headers are the key for success here. If you can provide some objc or c or c++ header to swift functions it becomes compatible and wise versa. I mean in general, thats the idea of headers. If you don't have headers, that does not mean you can not call some external stuff, it just means you would call it blind. A proper IDE will complain before you even try to do this evil stuff, unknown entry points aka unknown symbols etc.. So you go for a proper header - always.
To properly combine swift with other languages its good to know there are always two ways of bridging.
In case of Objective-C (and also Objective-C++) it is
Bridging into Swift (projectname-Bridging-Header.h),
and Bridging out of Swift (expose with #objc to trigger automatically internal generation of projectname-Swift.h file. So this header is "invisible" in the file browser on the left side. Nor will you find it in the repo as file, it is named by modulename which is the project-name). The last mentioned header you could even write manually yourself, with lots of troublesome back-draws.
Hint: Executable code is executable code. No matter what language, as far it is compiled for the right device architecture and has symbols to call and you know what to do with the data returned.
Another Hint: there is a way to handle C pointers in swift see docu which become swift datatypes which you can use to go the other way and declare functions to return those from swift.
And direct use of C in Swift is also possible. The compiler considers if you explicit mark some code as C. extern "C" { /* code */ } will cause the C++ compiler to remember, this is still C++ code to compile the function in such a way, it can be called from C (and Swift)
//Example.hpp //no target membership
#ifdef __cplusplus
#include <stdio.h>
class Example {
private:
const char * _name;
public:
Example(const char *name);
~Example(void);
int getLen(void);
};
#endif
There should be an Example.cpp and don't forget to tell Xcode you deal with c++ #ifdef __cplusplus + #endif
//Example.cpp //has target membership
#include "Example.hpp"
#ifdef __cplusplus
#include <stdio.h>
#include <string>
//code implementation according to example.hpp
Example::Example(const char *name) {
_name = name;
}
int Example::getLen() {
return (int)strlen(_name);
}
#endif
//ExampleWrapper.cpp //has target membership
#include "Example.hpp" //c++ header file
extern "C" int myCppFunction(const char *s)
{
// Create an instance of Example, defined in the library
// and call getLen() on it, return result.
return Example(s).getLen();
}
So this function needs to be declared in the bridging header to make use of it.
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// for extern "C" functions declare them one by one here
// as implemented in ExampleWrapper.cpp
// becomes "func myCppFunction(_ s: UnsafePointer<Int8>!) -> Int32" in swift
int myCppFunction(const char * s);
and then call from swift..
os_log("The result from C++ is %u", myCppFunction("12345"))
So in fact, yes. Integrating a static lib A that calls static lib B in App is possible. Happy compiling as long you offer some header for each part that needs to know what is inside the head of the other lib. That is true for Apps as it is true for libs and frameworks under each other.
Edit here some important stuff to read about Swift Package Manager C support https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md
As long as the libraries export Objective-C compatible symbols, it doesn't matter if they're written in Objective-C, or Swift, or C++, or any other compiled language.
And we know that the Swift compiler exports Objective-C compatible symbols for all declarations that are marked with #objc (either explicitly or implicitly).
From a consumer perspective it doesn't matter which language generated the libraries, as long as the Objective-C compiler/linker can consume the symbols exported by those libraries.
This question already has an answer here:
Force Header Files to Compile as C++ in Xcode
(1 answer)
Closed 2 years ago.
I'm trying to use a 3rd party sample code as part of my Objective-C application.
However, when trying to compile my project I get a lot of compiler errors.
The objc syntax that is used in the sample is quite strange and I believe that it is compiled as something else within the project.
For example, as part of the header file the struct definition has default values:
File.h
struct Options
{
int count = 100;
}
...
In their project, the above header file would compile just fine, but when I try to compile it I see an Xcode error:
Expected ';' at end of declaration list
I'm not an objective-c expert, but from what I've read and also found as part of other posts data types cannot have default values, but somehow it compiles fine in the Xcode sample app.
Please let me know if you need more info or other examples of what would compile fine in their project and doesn't work when I copy and paste the code into mine.
Edit:
Force Header Files to Compile as C++ in Xcode
Individually header files doesn't compiled. Compiled source files where they included. If you include them in .c they will be compiled like C, if in .m - like Objective-c, if in .cpp - like C++, if in .mm - like Objective-C++.
My issue was that I was using this header file into a .m file which compiles it to an Objective-C standard. When I change the extension to .mm everything worked fine.
When you think of objective-C as actually being C its more clear why defaults are not set in .h files
This does not apply to the rules of default sizes which are needed when no flexible memory allocation for a data type is available by default, like for (as is) most data types in C.
Even this two sentences already show the difficulty to distinguish what is meant with "default".
Which is why you end up with definition of initiation processes and functions to declare what exactly is "default" in the other file.
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int count;
} Options;
typedef struct {
int foo;
Options bar[100];
} Foo;
struct Bar {
Foo lotsof;
}
void MyInitiationFunction(Bar *b);
// definition of MyInitiationFunction in .m/.c file
#ifdef __cplusplus
}
#endif
but there is the concept of enum that can trick your mind where defined enumeration default states are what you build some stuff on, which is not a value.
Cocoa Touch Frameworks provide support for versioning, which can be found in Build Settings under the Versioning section.
To access this value at runtime, we can use the FrameworkVersionNumber and FrameworkVersionString[] variables which are auto-generated for us as part of the build process.
When working with a Swift project, these can be found auto-generated at the top of the Objective-C compatibility header:
//! Project version number for Framework.
FOUNDATION_EXPORT double FrameworkVersionNumber;
//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
However, whilst FrameworkVersionNumber is accessible from Swift, FrameworkVersionString[] is not. In fact looking at the contents of the framework module, I can see that only the first variable is exposed to Swift:
//! Project version number for Framework.
var FrameworkVersionNumber: Double
The problem with this is that since FrameworkVersionNumber is a Double, any version numbers like 3.2.1 simply get changed to 3.200000...
Does anyone know whether this is a flaw in my project setup, a bug in Xcode, or whether there is a way of getting the framework version in Swift as a String or array, so that I can provide more granular versioning than major.minor?
I have actually found a potential workaround for this issue, it's not so clean but it does work:
By default, when Xcode creates a framework it sets the Version to 1.0 and the Build to $(CURRENT_PROJECT_VERSION) which is great, because this value is actually being copied from the Current Project Version field in Build Settings > Versioning.
So what you can do to get this value at runtime is as follows:
let bundle = NSBundle(identifier: "com.yourframework.Framework")! // Get a reference to the bundle from your framework (not the bundle of the app itself!)
let build = bundle.infoDictionary![kCFBundleVersionKey] as! String // Get the build from the framework's bundle as a String
This does work but it feels quite circuitous for something that used to (I believe) be readily accessible from a variable in Objective-C.
IMPORTANT UPDATE - OCT 2021 - XCODE 13
When submitting an app to the App Store, Xcode 13 has a new option called "Manage Version and Build Number" which is ticked by default. If left checked, Xcode will automatically set your app's version number which (rather counter-intuitively), will also apply to all included frameworks. In other words, if your app version is 1.0, your framework version will be overwritten with 1.0.
Make sure you disable this option to avoid your framework version being overwritten.
You can also opt-out of this new behaviour by setting manageAppVersionAndBuildNumber in your export options plist.
For further details, see this discussion on the Apple Developer Forums.
These variables are populated in an automatically generated .c file when building from the project's CURRENT_PROJECT_VERSION. It looks like this:
extern const unsigned char FrameworkVersionString[];
extern const double FrameworkVersionNumber;
const unsigned char FrameworkVersionString[] __attribute__ ((used)) = "#(#)PROGRAM:Mark2SDK PROJECT:Framework-1" "\n";
const double FrameworkVersionNumber __attribute__ ((used)) = (double)1.;
The C array doesn't make it to Swift for some reason. Modifying the array definition to a pointer causes an EXC_BAD_ACCESS crash. What you can do though is create a pointer to the array and use that. In Framework.h:
//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
// add this
extern const unsigned char * FrameworkVersionStringPtr;
Then, either by creating Framework.c or in another c or m file, add this:
#import "Framework.h"
const unsigned char * FrameworkVersionStringPtr = FrameworkVersionString;
You can then use the string pointer in Swift to get the version:
func version() -> String? {
let ver = String(cString: Mark2SDKVersionStringPtr)
guard let range = ver.range(of: "-") else {
return nil
}
return String(ver[range.upperBound...])
}
print(version())
// 1.0.1
for swift 4.2 it works:
if let bundle = Bundle(identifier: "com.ingconti.SampleFramework") {
if let build = bundle.infoDictionary?["CFBundleShortVersionString"] {
print(build)
}
}
What is a good way to load a GLSL shader using C/C++ without using Objective-C or any Apple APIs?
I am currently using the following method, which is from the iPhone 3D Programming book, but it says that it is not recommended for production code:
Simple.vsh
const char* SimpleVertexShader = STRINGIFY
(
// Shader code...
);
RenderingEngine.cpp
#define STRINGIFY(A) #A
#include "Simple.vsh"
// ...
glShaderSource( shaderHandle, 1, &SimpleVertexShader, 0 );
If you want to load your shaders from files in your app bundle, you can get the file paths using the NSBundle object (in Objective-C), or using the CoreFoundation CFBundle object (in pure C).
Either way, you are using Apple-specific APIs. The only thing you're getting by using CFBundle instead of NSBundle is more boilerplate code.
If you don't want to use any Apple APIs, then your options are to embed your shaders as literal strings, or connect to a server on the Internet and download them (using the Unix socket API).
What you really need to do is define an interface by which your RenderingEngine gets the source code for its shaders, and implement that interface using the appropriate platform-specific API on each platform to which your port the RenderingEngine. The interface can be something super simple like this:
RenderingEngineShaderSourceInterface.h
#ifdef __cplusplus
extern "C" {
#endif
// You are responsible for freeing the C string that this function returns.
extern char const *RenderingEngine_shaderSourceForName(char const *name);
#ifdef __cplusplus
}
#endif
Then you create RenderingEngineShaderSource_Windows.cpp, RenderingEngineShaderSource_iOS.m, RenderingEngineShaderSource_Linux.cpp, etc. Each one implements RenderingEngine_shaderSourceForName using the appropriate API for that platform.
I use one of two methods. If it's a short shader, I may just put it code:
const char shader[] =
"uniform vec4 blah;\n" // Note, no semicolon here - it does the right thing
"main ()\n"
"{\n"
...rest of code
"}\n";
Or, if it's longer or going to be re-used in other places, I'll put it into a text file in the resources and read the text file at run time. You can get to it via [NSBundle pathForResource:ofType:].
Consider a C++ raw string literal; no STRINGIFY is needed since the newer features of C++ allow you to do similar things without macro.
I'd retype a good example but here is one.
I followed Claus's post to set up code coverage on Xcode 4.2 with LLVM 3.0. I'm able to see test coverage files, but they're only for my unit test classes, not my actual project classes. I've tried setting Generate Test Coverage Files and Instrument Program Flow to Yes on my main target, but that didn't help, as it failed with the following error:
fopen$UNIX2003 called from function llvm_gcda_start_file
To clarify, I don't think that's even the right approach - I just tried it to see if it would generate code coverage on my project classes.
At this point, I'd be happy to try anything that gets code coverage working on my app. Any suggestions?
You are expecting linker problem, profile_rt library uses fopen$UNIX2003 and fwrite$UNIX2003 functions instead of fopen and fwrite.
All you need is to add the following .c file to your project:
#include <stdio.h>
FILE *fopen$UNIX2003( const char *filename, const char *mode )
{
return fopen(filename, mode);
}
size_t fwrite$UNIX2003( const void *a, size_t b, size_t c, FILE *d )
{
return fwrite(a, b, c, d);
}
This code just remaps the missing functions to standard ones.
Note on $UNIX2003 suffix:
I've found an Apple document saying:
The UNIX™ conformance variants use the $UNIX2003 suffix.
Important: The work for UNIX™ conformance started in Mac OS 10.4, but was not completed until 10.5. Thus, in the 10.4 versions of libSystem.dylib, many of the conforming variant symbols (with the $UNIX2003 suffix) exist. The list is not complete, and the conforming behavior of the variant symbols may not be complete, so they should be avoided.
Because the 64-bit environment has no legacy to maintain, it was created to be UNIX™ conforming from the start, without the use of the $UNIX2003 suffix. So, for example, _fputs$UNIX2003 in 32-bit and _fputs in 64-bit will have the same conforming behavior.
So I expect libprofile_rt to be linked against 10.4 SDK.
I use CoverStory http://code.google.com/p/coverstory/ a GUI for .gcda and .gcno files.
The documentation explains the settings needed to generate these files http://code.google.com/p/coverstory/wiki/UsingCoverstory.