After reimplement many features several times in different platforms is time to think that it should be a better way. There are many frameworks that allows the developers to write the code once and deploy it "everywhere", but the final result is an app with a non native look and feel or with an emulated look and feel that the users can see and rate according to the quality.
There are other ways to develop apps for multiple platforms without rewriting the same code over and over. I'll talk about one of that ways which consists on developing the core with C++ and implement the UI natively. This method could sound very scary because of the C++ reputation (memory leaks, the standard library, etc), but with C++11 all this has been improved in a very sweet way, so maybe it is time to take an other look at this language and see how can we take advantage of it.
12. The compiler deduce the actual type of a variable that
is being declared from its initializer.
auto i = 42; // i is an int
auto l = 42LL; // l is an long long
auto p = new Foo(); // p is a foo*
std::map<std::string, std::vector<int>> map;
for(auto it = begin(map); it != end(map); ++it)
{
}
11
13. Support the "foreach" paradigm of iterating over
collections.
std::map<std::string, std::vector<int>> map;
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
map["one"] = v;
for(const auto& kvp : map)
{
std::cout << kvp.first << std::endl;
for(auto v : kvp.second)
std::cout << v << std::endl;
}
12
14. Before:
Implicitly converted to integral types
Export their enumerators in the surrounding scope,
which can lead to name collisions
No user-specified underlying type
enum class Options {None, One, All};
Options o = Options::All;
13
15. unique_ptr: Ownership of a memory resource it is not
shared, but it can be transferred to another unique_ptr
shared_ptr: Ownership of a memory resource should be
shared
weak_ptr: Holds a reference to an object managed by a
shared_ptr, but does not contribute to the reference count;
it is used to break dependency cycles.
14
16. Powerful feature borrowed from functional
programming.
You can use lambdas wherever a function object or a
functor or a std::function is expected
std::function<int(int)> lfib = [&lfib](int n) {
return n < 2 ? 1 : lfib(n-1) + lfib(n-2);
};
15
17. static_assert performs an assertion check at compile-time
template <typename T1, typename T2>
auto add(T1 t1, T2 t2) -> decltype(t1 + t2)
{
return t1 + t2;
}
std::cout << add(1, 3.14) << std::endl;
std::cout << add("one", 2) << std::endl;
template <typename T1, typename T2>
auto add(T1 t1, T2 t2) -> decltype(t1 + t2)
{
static_assert(std::is_integral<T1>::value, "Type T1 must be integral");
static_assert(std::is_integral<T2>::value, "Type T2 must be integral");
return t1 + t2;
}
16
18. Final and overview
non-member begin() and end()
Initializer lists
Object construction improvement
Unrestricted unions
User-defined literals
…
17
20. C++ 11 is missing utilities
A standard way to make requests
Dealing with XML or JSON
Big numbers
Security
Math
…
Solution: Use it with other libraries
19
26. Declare the native method on java
private native void doSomethingNative(String str);
Implement the C method
JNIEXPORT void Java_com_example_MyClass_doSomethingNative (JNIEnv *env, jobject obj,
jstring s)
{
const char* const utf8 = env->GetStringUTFChars (s, nullptr);
CharPointer_UTF8 utf8CP (utf8);
String cppString (utf8CP);
env->ReleaseStringUTFChars (s, utf8);
doSomethingWithCppString (cppString);
}
Do not forget to release the java objects!
env->Release: The maxim number of java references is 512
Some libraries offers you utilities to parse common java
objects to Cpp objects
25
27. Declare the native method on java
JNIEnv* env = getEnv();
jclass myJavaClass = env->GetObjectClass (myJavaObject);
jmethodID myJavaMethod = env->GetMethodID(myJavaClass , ”methodName", "([I;Z)Ljava/lang/String");
jstring jresult = (jstring) env->CallObjectMethod (myJavaObject, myJavaMethod , myIntArray, myBoolean);
// Do something
env->DeleteLocalRef (jresult);
env->DeleteLocalRef (myJavaClass);
Do not forget to delete the local java references
env->DeleteLocalRef: The maxim number of java
references is 512
26
28. Java
public class Foo {
private static native void destroyCppInstanceNative(long ref);
private native long newCppInstanceNative();
private native String getStringNative(long ref);
private long _ref = 0;
public Foo() {
_ref = newCppInstanceNative();
}
public String getString() {
return getStringNative(_ref);
}
public void destroy() {
destroyCppInstanceNative(_ref);
}
}
27
30. On Objective-C++ is very easy to use C++
The extension of the Objective-C++ file is .mm
Try to do not add imports of C++ code on the Objective-C headers
If you add a C++ import in your Objective-C header you will force
other classes to be Objective-C++ (.mm) instead of Objective-C
(.m)
@implementation JSPFoo
Foo fooObject;
-(id) init {
self = [super init];
if (self) {
}
return self;
}
- (NSString*) stringFromCpp
{
NSString* result = [NSString stringWithUTF8String:fooObject.getString().toRawUTF8()];
return result;
}
@end 29
31. Establish some code conventions with your coworkers
Review each others code
If you do not find the C++ code that you need just create
some interfaces and implement them in the native
platform (java, Objective-c, C# … )
Code as if you where creating a library, if you have more
apps to develop this code will help you
C++ is not a read-only code, so do not put the blame on it
30
32. Remember to initialize all the values in the constructor,
even numbers…
To speed up the compilation time use unity builds
Check out djinni: tool for generating cross-language type
declarations and interface bindings.
dropbox/djinni
31
34. Pros
Different apps sharing the same core and with native
UI/UX
Better performance
Faster development
Easier maintenance
Cons
Need to learn a new language
Android apps will be bigger (code compiled for different
architectures)
Can be fixed distributing specific apk per each architecture
33