Developing iOS apps using the Go Language (Swift edition)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

This article assumes that the reader has a certain understanding of the go language and the swift language, but does not understand the mix of students.

This tutorial is a simple summary based on a real-world iOS app.

Let's look at the effect of the operation first:

Scan Code Installation:

Background

The go language is a programming language for Web services and multi-concurrency environments that Google Inc. has open source in 2010, and is characterized by simplicity. But because it is simple, it can only achieve 90% performance, which is the biggest advantage of go language, because less is more reason than everyone can understand.

Swift is the language that Apple Inc. released in 2014 to replace Objectivec, primarily for interface program development on iOS and OS X. Of course, using Swift to develop the server is also a field of concern, the author is optimistic in the near future swift will gradually replace the C + + and rust language.

The go language and swift language are original two languages, why do they have to be all together? The reason is very simple, because the author is a go powder, but also a half of swift powder, want to test the development of iOS, but really can not stand Objectivec binding cloth grammar.

Add: Although I do not like the Objectivec grammar, but feel that the Objectivec of the runtime is very tough. In theory, Objectivec-based runtime can be used to develop iOS applications in any popular programming language, Rubymotion is an example.

In fact, most popular languages now have a intersection, is the C language compatible binary interface. So, the C + + popularity is not more than C + +, but it chose to seamlessly compatible with the C language of the vast majority of specifications.

However, there are drawbacks to the specification of a fully compatible C language, which is that language itself cannot be developed freely, because many places are constrained by the C programming model. C + + and Objectivec are two examples that are more representative.

So, Swift was born only compatible with the C language of the binary interface specification, while holding tight Objectivec's runtime thigh, and go to their own really have a great quality.

However, for the time being we don't care about the hybrid programming of Swift and Objectivec, we only focus on how the C language, as a subset of Objectivec, is programmed with Swift.

Swift calls the C function

Swift calls C functions in a number of ways: through Objectivec bridging calls and direct calls. In fact, the principle of the two is the same, I personally like to choose the most direct and most violent direct call C function of the way.

For example, there is a C function:

#include 
  
   
    
   void getInput(int *output) {    scanf("%i", output);}
  
   

Generate a bridged header file xxx-Bridging-Header.h that contains the C function specification:

void getInput(int *output);

Swift can be used directly:

import Foundationvar output: CInt = 0getInput(&output)println(output)

If you do not need to bridge the file, you can declare a swift function in Swift, corresponding to the C function:

@_silgen_name("getInput") func getInput_swift(query:UnsafePointer
  
   
    
   )
  
   

To clearly differentiate the C function from the SWIFT function, we will getInput re-declare it as getInput_swift , using the same method as before:

import Foundationvar output: CInt = 0getInput_swift(&output)println(output)

How to manage the memory returned by C in Swift

The swift language itself is self-bringing arc, and the user is rarely directly concerned with memory issues. However, if the C function returns memory to Swift space, Swift's arc is invalid and requires manual release of C memory.

Let's say we implement a function of string cloning in C language:

char* MyStrDup(char* s) {    return strdup(s);}

This can be used in swift:

@_silgen_name("MyStrDup")func MyStrDup_swift(query:UnsafePointer
  
   
    
   ) -> UnsafeMutablePointer
   
    
     
    let p = MyStrDup_swift("hello swift-c!")let s = String.fromCString(p)!p.dealloc(1)
   
    
  
   

String.fromCString(p)!build a swift string from the C string, and then call p.dealloc(1) Free the C-string memory space manually.

function calls and memory management are two of the most important fundamental issues in cross-language programming, and it is now possible to work on them for a long time.

Go language export C static Library

The go language provides a CGO tool for the Go language and C language interaction. This is an example of the go language using the C language:

package main//#include 
  
   
    
   import "C"func main() {    C.puts(C.CString("abc"))}
  
   

Since we want to interact, it will naturally involve the case of the C language callback to the Go language function. To do this, CGO provides a export comment command that generates a C-language function corresponding to the Go language function:

//export MyStrDupfunc MyStrDup(s *C.char) *C.char {    return C.strdup(s)}

MyStrDupThe specified name must be the same as the Go function name, and the function's argument is the type supported by the C language.

Now we have the functions implemented in the Go language MyStrDup , using the same method as in the previous C language MyStrDup .

As with the problem of referencing the C language library, how do we reference the C code or the function implemented by the go code in the project?

The answer is also from C: Build the code into a C static library or C dynamic library, and then import a static or dynamic library into the Swift project.

However, for iOS, the process of building a C static library or C dynamic library is cumbersome (using Xcode only hides the concrete steps of the build).

Because iOS involves a variety of CPU architectures: Emulator x86, 4s 32-bit arm, 5s after 64-bit arm,64-bit arm also has a different version ...

This is the C static library or C dynamic Library construction always have to face the problem.

Parameters for cross-construction

After Go1.6 added support for building C static libraries, cross-compiling is also very simple and only needs to be set up GOARCH and GOOS on the line.

Because GOOS there is only Darwin one type of iOS, we just need to set GOARCH it up.

To build a C static library, we need to put the above MyStrDup implementation into a main package:

package main//#include 
  
   
    
   import "C"func main() {    //}//export MyStrDupfunc MyStrDup(s *C.char) *C.char {    return C.strdup(s)}
  
   

mainThe function in the package main is not executed, but the init function is still valid.

Use the following command to build a C static library of the current system:

go build -buildmode=c-archive

To cross-compile the available C-static libraries for iOS, we need to set up the GOARCH CGO feature at the same time (cross-compile, CGO is off by default).

Here is a C static library that builds the X86/AMD64 type for the emulator:

export CGO_ENABLED=1export GOARCH=amd64go build -buildmode=c-archive -o libmystrdup_amd64.a

We use -o parameters to specify the static library file name for the output. The build command also generates a header file (which may be called libmystrdup_386.h ), which we do not use to delete the header file directly.

Here is a C static library that builds the x86/386 type for the emulator:

export CGO_ENABLED=1export GOARCH=386go build -buildmode=c-archive -o libmystrdup_386.a

There may be some link errors when building a C static library of type x86/386, and we will avoid this for the time being.

Create a patch_386.go file:

// Copyright 2016 
  
   
    
   . All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// 针对iOS模拟器link时缺少的函数// 属于临时解决方案package main/*#include 
   
    
     
    #include 
    
     
      
     #include 
     
      
       
      #include 
      
       
         size_t fwrite$UNIX2003(const void* a, size_t b, size_t c, FILE* d) { return fwrite(a, b, c, d);}char* strerror$UNIX2003(int errnum) { return strerror(errnum);}time_t mktime$UNIX2003(struct tm * a) { return mktime(a);}double strtod$UNIX2003(const char * a, char ** b) { return strtod(a, b);}int setenv$UNIX2003(const char* envname, const char* envval, int overwrite) { return setenv(envname, envval, overwrite);}int unsetenv$UNIX2003(const char* name) { return unsetenv(name);}*/import "C" 
       
     
      
    
     
   
    
  
   

Of course, there will be some warnings, temporarily ignoring them.

Building a static library of multi-CPU types

Then, add the C static library to the iOS Xcode project file.

X86 builds are relatively straightforward because we can use local build commands by default. However, if you want to build a static library of arm, you need to configure the build environment first.

I've deducted a script from the Go Code clangwrap.sh (as if it were in a $GOROOT/misci/ios directory):

#!/bin/sh# This uses the latest available iOS SDK, which is recommended.# To select a specific SDK, run 'xcodebuild -showsdks'# to see the available SDKs and replace iphoneos with one of them.SDK=iphoneosSDK_PATH=`xcrun --sdk $SDK --show-sdk-path`export IPHONEOS_DEPLOYMENT_TARGET=7.0# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang.CLANG=`xcrun --sdk $SDK --find clang`if [ "$GOARCH" == "arm" ]; then    CLANGARCH="armv7"elif [ "$GOARCH" == "arm64" ]; then    CLANGARCH="arm64"else    echo "unknown GOARCH=$GOARCH" >&2    exit 1fiexec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH "$@"

It is more important that the IPHONEOS_DEPLOYMENT_TARGET environment variable, which means that the target minimum support ios7.0 system.

To build a static library of ARM64 environments:

export CGO_ENABLED=1export GOARCH=arm64export CC=$PWD/clangwrap.shexport CXX=$PWD/clangwrap.shgo build -buildmode=c-archive -o libmystrdup_arm64.a

To build a static library of ARMV7 environments:

export CGO_ENABLED=1export GOARCH=armexport GOARM=7export CC=$PWD/clangwrap.shexport CXX=$PWD/clangwrap.shgo build -buildmode=c-archive -o libmystrdup_armv7.a

Then we use the lipo command to package these different static libraries into a static library:

lipo libmystrdup_386.a libmystrdup_adm64.a libmystrdup_arm64.a libmystrdup_armv7.a -create -output libmystrdup.a

In this way, you can support targets for different CPU types as long as you introduce a static library.

Summarize

Chairman Mao taught us that we should learn war in war.

Pheasant Hospital This app is the author's first iOS app, and this tutorial is also the result of a step-through learning summary in the iOS development process. There must be a lot of inaccuracies in the description, and the authors welcome any different opinions or suggestions.

A complete example:

    • AppStore Installation: HTTPS://APPSTO.RE/CN/QH8OCB.I
    • Swift Project: Https://github.com/chai2010/ptyy/tree/master/ios-app/yjyy-swift
    • Go Static Library project: Https://github.com/chai2010/ptyy/tree/master/cmd/yjyy
    • Static Library build script: https://github.com/chai2010/ptyy/tree/master/ios-app/yjyy-swift/vendor/gopkg

All codes can be obtained free of charge (BSD protocol): Https://github.com/chai2010/ptyy

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.