Lädt...


🔧 How to use GoLang in Flutter Application - Golang FFI


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

GoLang is a very powerful language that is easy to use. Writing a GoLang program and compiling it to a binary file is very easy. Golang is very useful in writing high-performance and low-latency applications, but it needs improvement in GUI. Flutter is a compelling cross-platform UI framework. It allows you to write a beautiful application effortlessly. Mixing GoLang and Flutter is an excellent idea to write a high-performance and beautiful application.

In this article, we will see how to compile a GoLang-based library and create a Flutter plugin package for a Flutter application.

What is FFI?

FFI stands for Foreign Function Interface. It is a way to call functions written in other languages from Dart. FFI helps use libraries written in other languages in a Flutter application. Flutter supports FFI for Android, iOS, Linux, macOS, and Windows. In this article, we will see how to use FFI.

In Dart, the programming language used to write Flutter applications, we can use the dart:ffi package to use FFI. The dart:ffi package is used to call functions written in other languages from Dart. We can use the dart:ffi package to call functions written in C, C++, or Rust. In this article, we will see how to use the dart:ffi package to call functions in GoLang.

Create a plugin project for Flutter

The Flutter plugin can contain Dart and platform-specific code written in Kotlin, Swift, Objective-C, or GoLang. We can use a Flutter plugin to add functionality to a Flutter application.

The below command will create a Flutter plugin project named native_add. The native_add project will support Android, iOS, Linux, macOS, and Windows. The native_add project will have a lib folder that contains the Dart code and an example folder that contains a Flutter application to test the plugin.

 $ flutter create --platforms=android,ios,macos,windows,linux --template=plugin_ffi native_add
 $ cd native_add

Create a GoLang library

The plugin project we created in the previous step will have a src folder. The src folder will have a cpp folder that contains the C++ code. We will create a GoLang library in the src folder. The GoLang library will have a function to add two numbers.

First, we will create a go.mod file. The go.mod file defines the module name and the GoLang version. The go.mod file is used to manage dependencies. We will not use any dependencies in this article.

// go.mod file
module go_code

go 1.21.3

Second, we will create a sum.go file. The sum.go file will have a function to add two numbers. The sum.go file will also have a function called enforce_binding. The enforce_binding function enforces the binding in the ios application. The Dart code will not use the enforce_binding function, but it was the trick I found to make the library linked correctly for iOS.

Above each function we want to expose, we will add a comment //export <function_name>. The //export <function_name> comment exposes the function to other languages. We must also use the type C.int instead of int in the function signature. The C.int type is used to make the function compatible with other languages.

// sum.go file
package main

import "C"

//export sum
func sum(a C.int, b C.int) C.int {
  return a + b
}

//export enforce_binding
func enforce_binding() {}

func main() {}

Compile the GoLang library for Android

Since we are compiling the GoLang library for Android, we must use cross-compilation. Modern Android devices mostly use arm64 or x86_64 architectures. We will compile the GoLang library for both arm64 and x86_64 architectures.

export ANDROID_OUT=../android/src/main/jniLibs
export ANDROID_SDK=$(HOME)/Library/Android/sdk
export NDK_BIN=$(ANDROID_SDK)/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin

# Compile for x86_64 architecture and place the binary file in the android/src/main/jniLibs/x86_64 folder
CGO_ENABLED=1 \
GOOS=android \
GOARCH=amd64 \
CC=$(NDK_BIN)/x86_64-linux-android21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/x86_64/libsum.so .

# Compile for arm64 architecture and place the binary file in the android/src/main/jniLibs/arm64-v8a folder
CGO_ENABLED=1 \
GOOS=android \
GOARCH=arm64 \
CC=$(NDK_BIN)/aarch64-linux-android21-clang \
go build -buildmode=c-shared -o $(ANDROID_OUT)/arm64-v8a/libsum.so .

Now we can use the libsum library in the Dart code using FFI.

DynamicLibrary.open('libsum.so');

Compile the GoLang library for iOS

We need some extra steps to cross-compile the Golang library and use it for iOS. iOS only supports static libraries. So, we need to compile the GoLang library as a static library. We also need to modify the podspec file to use the static library in the Flutter plugin. Another thing to note is that we need to create xcframework for iOS. The xcframework is used to support both simulator and device architectures.

# build_ios.sh file
#!/bin/sh
export GOOS=ios
export CGO_ENABLED=1
# export CGO_CFLAGS="-fembed-bitcode"
# export MIN_VERSION=15

SDK_PATH=$(xcrun --sdk "$SDK" --show-sdk-path)

if [ "$GOARCH" = "amd64" ]; then
    CARCH="x86_64"
elif [ "$GOARCH" = "arm64" ]; then
    CARCH="arm64"
fi

if [ "$SDK" = "iphoneos" ]; then
  export TARGET="$CARCH-apple-ios$MIN_VERSION"
elif [ "$SDK" = "iphonesimulator" ]; then
  export TARGET="$CARCH-apple-ios$MIN_VERSION-simulator"
fi

CLANG=$(xcrun --sdk "$SDK" --find clang)
CC="$CLANG -target $TARGET -isysroot $SDK_PATH $@"
export CC

go build -trimpath -buildmode=c-archive -o ${LIB_NAME}_${GOARCH}_${SDK}.a

The above script will create a static library for iOS. We must use the script to build the static library for both simulator and device architectures.


# Compile for x86_64 simulator architecture
GOARCH=amd64 \
SDK=iphonesimulator \
LIB_NAME=libsum \
./build_ios.sh

# Compile for arm64 simulator architecture
GOARCH=arm64 \
SDK=iphonesimulator \
LIB_NAME=libsum \
./build_ios.sh

# Compile for arm64 device architecture
GOARCH=arm64 \
SDK=iphoneos \
LIB_NAME=libsum \
./build_ios.sh

The above script will create three static libraries. Before creating the xcframework, we must combine the two static libraries for the simulator architecture. The lipo command can combine the two static libraries.

lipo \
-create \
libsum_arm64_iphonesimulator.a \
libsum_amd64_iphonesimulator.a \
-output libsum_iphonesimulator.a

Now we can create the xcframework using the below command.

xcodebuild -create-xcframework \
-output ../ios/libsum.xcframework \
-library ios-arm64/libsum.a \
-headers ios-arm64/libsum.h \
-library ios-simulator/libsum.a \
-headers ios-simulator/libsum.h

The libsum.xcframework will be created in the ios folder.

We need to modify the podspec file to use the xcframework. We must add the lines below to the podspec file under the ios folder.

s.public_header_files = 'Classes/**/*.h'
s.vendored_frameworks = 'libsum.xcframework'

After some trial and error, I found that we need to use the library in the Classes folder to link it properly. So, we create binding.h and EnforceBinding.swift files under the Classes folder.

The binding.h file will have the below code.

void enforce_binding();

The EnforceBinding.swift file will have the below code.

public func dummyMethodToEnforceBundling() {
    enforce_binding() // disable tree shaking
}

Now, we can use the libsum library in the Dart code using FFI.

// The libsum library is statically linked in the native_add so we only need to load native_add.
DynamicLibrary.open('$native_add.framework/native_add');

Create a binding in Dart using ffigen

The ffigen tool generates the Dart code to use the GoLang library. We will create a ffigen.yaml file to configure the ffigen tool. The config.yaml file will have the below code.

# Run with `flutter pub run ffigen --config ffigen.yaml`.
name: NativeLibrary
description: Bindings to `src/sum.h`.
output: 'lib/generated_bindings.dart'
headers:
  entry-points:
    - 'src/libsum.h'
preamble: |
  // ignore_for_file: always_specify_types
  // ignore_for_file: camel_case_types
  // ignore_for_file: non_constant_identifier_names
  // ignore_for_file: unused_field
  // ignore_for_file: unused_element
comments:
  style: any
  length: full

Now, we can run the ffigen tool to generate the Dart code.

flutter pub run ffigen --config ffigen.yaml

The ffigen tool will generate the generated_bindings.dart file under the lib folder based on the libsum.h file in src folder that was generated by the go build command in the previous step.

Use the GoLang library in Dart

Now, we can use the GoLang library in the Dart code. We can use the DynamicLibrary.open method to load the library. We can use the NativeLibrary class to call the functions in the GoLang library.

// lib/native_add.dart
import 'dart:ffi';
import 'dart:io';

import 'generated_bindings.dart';

int sum(int a, int b) => _bindings.sum(a, b);

const String _libName = 'native_add';

/// The dynamic library in which the symbols for [NativeAddBindings] can be found.
final DynamicLibrary _dylib = () {
  if (Platform.isMacOS || Platform.isIOS) {
    return DynamicLibrary.open('$_libName.framework/$_libName');
  }
  if (Platform.isAndroid || Platform.isLinux) {
    return DynamicLibrary.open('libsum.so');
  }
  if (Platform.isWindows) {
    return DynamicLibrary.open('$_libName.dll');
  }
  throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();

/// The bindings to the native functions in [_dylib].
final NativeLibrary _bindings = NativeLibrary(_dylib);

Now, we can use the sum function in the Dart code from the Flutter project that uses this plugin.

import 'package:native_add/native_add.dart' as native_add;
native_add.sum(1, 2);

Conclusion

In this article, we checked how to use GoLang in a Flutter application. We created a GoLang library and compiled it for Android and iOS. We also created a Flutter plugin to use the GoLang library in a Flutter application. We used the ffigen tool to generate the Dart code to use the GoLang library. We also checked how to use the GoLang library in the Dart code.

I also created a sample project to demonstrate using GoLang in a Flutter application. You can find the sample project in the below link. The example also contains the script to compile the GoLang library for MacOS.
https://github.com/leehack/flutter_golang_ffi_example
It's still missing for Windows and Linux but it should be much easier than for Android and iOS. Like Android or iOS, we must cross-compile and link the GoLang library for Windows and Linux in the CMake file.

Due to the lack of information, I had to spend a lot of time figuring out how to use GoLang in a Flutter application. This article will help you to use GoLang in a Flutter application.

...

🎥 Flutter Performance, Flutter Games, Flutter Tooling, & More (#AskFlutter at Flutter Live)


📈 43.55 Punkte
🎥 Videos

🔧 Flutter news from GDD China: uniting Flutter on web and mobile, and introducing Flutter 1.9


📈 32.66 Punkte
🔧 Programmierung

🎥 Origin of Flutter, Dart 2.0, E-Commerce with Flutter, & More (#AskFlutter at Flutter Live)


📈 32.66 Punkte
🎥 Videos

⚠️ [webapps] PHP 7.4 FFI - 'disable_functions' Bypass


📈 28.96 Punkte
⚠️ PoC

🕵️ ruby-ffi up to 1.9.23 on Windows DLL Loader privilege escalation


📈 28.96 Punkte
🕵️ Sicherheitslücken

🕵️ ruby-ffi bis 1.9.23 auf Windows DLL Loader erweiterte Rechte


📈 28.96 Punkte
🕵️ Sicherheitslücken

🔧 Mixing FFI, Fiddle, and C Extension in Ruby


📈 28.96 Punkte
🔧 Programmierung

⚠️ #0daytoday #PHP 7.4 FFI - (disable_functions) Bypass Exploit [webapps #exploits #0day #Exploit]


📈 28.96 Punkte
⚠️ PoC

💾 PHP 7.4 FFI disable_functions Bypass


📈 28.96 Punkte
💾 IT Security Tools

⚠️ PHP 7.4 FFI disable_functions Bypass


📈 28.96 Punkte
⚠️ PoC

🔧 Flutter Version Management A Guide to Effortless Project Switching in Flutter News 2024 #25 ʚїɞ


📈 21.78 Punkte
🔧 Programmierung

🎥 Flutter Design (Flutter Live)


📈 21.78 Punkte
🎥 Videos

🎥 Flutter code push with Shorebird | Observable Flutter #46


📈 21.78 Punkte
🎥 Video | Youtube

🎥 Flutter Live - Flutter Announcements and Updates (Livestream)


📈 21.78 Punkte
🎥 Videos

🎥 Exploring Flutter Samples and Examples (The Boring Flutter Development Show, Ep. 11)


📈 21.78 Punkte
🎥 Videos

🔧 Oficial! Gemini Google AI Dart/Flutter SDK— Integrando Flutter com o GEMINI


📈 21.78 Punkte
🔧 Programmierung

🎥 Flutter's Search Support - The Boring Flutter Development Show


📈 21.78 Punkte
🎥 Videos

🔧 Learn Flutter by creating your first Flutter app!


📈 21.78 Punkte
🔧 Programmierung

🎥 Publishing a Flutter App to the Play Store (The Boring Flutter Development Show, Ep. 8.4)


📈 21.78 Punkte
🎥 Videos

🔧 Flutter Tutorial – How to Develop an App with Flutter From Scratch


📈 21.78 Punkte
🔧 Programmierung

🎥 Alibaba used Flutter to build 50+ million user Xianyu app (Flutter Developer Story)


📈 21.78 Punkte
🎥 Videos

🔧 Flutter 3.19 just released - Flutter News 2024 #7 ʚїɞ


📈 21.78 Punkte
🔧 Programmierung

🎥 How to Publish a Flutter Package - The Boring Flutter Development Show, Ep. 7.3


📈 21.78 Punkte
🎥 Videos

🎥 Q&A and Tour of Flutter Samples Index - The Boring Flutter Development Show, Ep. 7.4


📈 21.78 Punkte
🎥 Videos

🔧 Flutter Hooks Tutorial: Flutter Animation Using Hooks (useEffect and useAnimationController)


📈 21.78 Punkte
🔧 Programmierung

🎥 Adding a Streams API to a Flutter Plugin - The Boring Flutter Development Show, Ep. 7.5


📈 21.78 Punkte
🎥 Videos

🕵️ Reverse Engineering a Flutter app by recompiling Flutter Engine


📈 21.78 Punkte
🕵️ Reverse Engineering

📰 FLUTTER & DART – THE COMPLETE FLUTTER APP DEVELOPMENT COURSE


📈 21.78 Punkte
📰 Alle Kategorien

🎥 Google Maps for Flutter, Platform Channels, Mobile Ads, & More - #AskFlutter at Flutter Live


📈 21.78 Punkte
🎥 Videos

🔧 Say Hello to Flutter GPT: Your New Flutter Development Buddy 🚀


📈 21.78 Punkte
🔧 Programmierung

🎥 Hamilton app built with Flutter and featured on iOS and Android (Flutter Developer Story)


📈 21.78 Punkte
🎥 Videos

🎥 Flutter Development (Flutter Live)


📈 21.78 Punkte
🎥 Videos

🔧 Implementing design systems in flutter: Flutter Mix Primer.


📈 21.78 Punkte
🔧 Programmierung

🎥 Hamilton app built with Flutter and featured on iOS and Android (Flutter Developer Story)


📈 21.78 Punkte
🎥 Videos

matomo