박제창 (@Dreamwalker)
Flutter Seoul
GDG Golang Korea
2
Slide 3
Slide 3 text
Flutter is an open source
framework by Google for
building
beautiful,
natively compiled,
multi-platform applications
from a single codebase.
3
Slide 4
Slide 4 text
Flutter is an open source
framework by Google for
building
beautiful,
natively compiled,
multi-platform applications
from a single codebase.
4
Slide 5
Slide 5 text
Flutter is an open source
framework by Google for
building
beautiful,
natively compiled,
multi-platform applications
from a single codebase.
5
Slide 6
Slide 6 text
Flutter Multi-Platform
Mobile
Bring your app idea to
more users from day
one by building with
Flutter on iOS and
Android simultaneously,
without sacrificing
features, quality, or
performance.
Web
Easily reach more
users in browsers
with the same
experience as on
mobile devices
through the power
of Flutter on the
web.
Desktop & Embedded
Build high-quality desktop
apps without compromising
compatibility or
performance.
Flutter's support for custom
embedders means you can
create new ways to put
Flutter to work on the
platforms that matter to you.
6
OS architecture
8
Source: https://linux-kernel-labs.github.io/refs/heads/master/lectures/arch.html
Slide 9
Slide 9 text
Dart’s compiler technology
9
Source: https://dart.dev/overview#platform
Native platform: For apps
targeting mobile and desktop
devices, Dart includes both a Dart
VM with just-in-time (JIT)
compilation and an ahead-of-time
(AOT) compiler for producing
machine code.
Web platform: For apps targeting
the web, Dart can compile for
development or production
purposes. Its web compiler
translates Dart into JavaScript.
Slide 10
Slide 10 text
Flutter Multi-Platform
10
Slide 11
Slide 11 text
ffi
foreign function
interface
Incheon/Songdo
11
Slide 12
Slide 12 text
foreign function interface
1. JavaScript interoperability
2. C interoperability
3. ffi gen
4. JNI (gen)
12
Slide 13
Slide 13 text
foreign function interface
1. JavaScript interoperability
2. C interoperability
3. ffi gen
4. JNI (gen)
13
Part. 1
Slide 14
Slide 14 text
foreign function interface
A foreign function interface (FFI) is a mechanism by which a
program written in one programming language can call routines or
make use of services written or compiled in another one.
An FFI is often used in contexts where calls are made into
binary dynamic-link library.
14
Slide 15
Slide 15 text
Interoperability
C → C interop → dart:ffi or package:ffigen
Objective-C & Swift ⇒ dart:ffi or package:ffigen
Java & Kotlin ⇒ package:jni or package:jnigen
javaScript ⇒ package:js & dart2wasm
Dart2wasm
Dart SDK >= 2.19
Package:js >=0.6.6
15
JavaScript interoperability
18
function adder(a, b) {
return a + b;
}
Slide 19
Slide 19 text
JavaScript interoperability
19
untitled
// The value below is injected by flutter build, do not touch.
const serviceWorkerVersion = null;
Slide 20
Slide 20 text
JavaScript interoperability
20
@JS()
library adder;
import 'package:js/js.dart';
@JS()
external int adder(int a, int b);
Slide 21
Slide 21 text
JavaScript interoperability
21
@JS()
library adder;
import 'package:js/js.dart';
@JS()
external int adder(int a, int b);
function adder(a, b) {
return a + b;
}
C interoperability
33
● C언어를 활용한 함수를 Dart 언어를 통해 호출하여 사용하는
방법
● C/C++ 라이브러리를 Dart언어로 사용하는 방법
Dart ffi
main.dart
Dart
OS
xxx.dylib or so
C&C++
Slide 34
Slide 34 text
preparation
34
● cmake
○ CMake is cross-platform free and open-source software for build automation,
testing, packaging and installation of software by using a
compiler-independent method. CMake is not a build system itself; it
generates another system's build files
● make
○ Make is a build automation tool that builds executable programs and libraries
from source code by reading files called makefiles which specify how to
derive the target program.
● gcc
● etc..
Slide 35
Slide 35 text
C interoperability
35
● hello_world.h
void hello_world();
C&C++
C interoperability
37
CMakeLists.txt
cmake_minimum_required(VERSION 3.7 FATAL_ERROR)
project(hello_world_library VERSION 1.0.0 LANGUAGES C)
add_library(hello_world_library SHARED hello_world.c hello_world.def)
add_executable(hello_test hello_world.c)
set_target_properties(hello_world_library PROPERTIES
PUBLIC_HEADER hello_world.h
VERSION ${PROJECT_VERSION}
SOVERSION 1
OUTPUT_NAME "hello_world"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here"
)
Slide 38
Slide 38 text
C interoperability
38
$> cmake . // cmake를 통해 빌드 파일 생성
$> make // 생성된 빌드 파일을 기반으로 빌드 진행
Slide 39
Slide 39 text
C interoperability
39
jaichang@PARKui-MacBookPro % cmake .
-- The C compiler identification is AppleClang 15.0.0.15000040
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done (1.1s)
-- Generating done (0.0s)
-- Build files have been written to: /hello_world_library
jaichang@PARKui-MacBookPro % make
[ 25%] Building C object CMakeFiles/hello_world_library.dir/hello.c.o
[ 50%] Linking C shared library libhello.dylib
[ 50%] Built target hello_world_library
[ 75%] Building C object CMakeFiles/hello_test.dir/hello.c.o
[100%] Linking C executable hello_test
[100%] Built target hello_test
Slide 40
Slide 40 text
C interoperability
40
● hello_world.dart
1. Open DynamicLibrary file
2. Lookup Functions
3. Run
dart
Slide 41
Slide 41 text
C interoperability
41
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final void Function() hellos = dylib
.lookup>('hello_world')
.asFunction();
dart
Slide 42
Slide 42 text
C interoperability
42
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final void Function() hellos = dylib
.lookup>('hello_world')
.asFunction();
dart
Slide 43
Slide 43 text
C interoperability
43
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final void Function() hellos = dylib
.lookup>('hello_world')
.asFunction();
dart
Slide 44
Slide 44 text
C interoperability
44
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final void Function() helloWorld = dylib
.lookup>('hello_world')
.asFunction();
dart
Slide 45
Slide 45 text
C interoperability
45
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final void Function() hellos = dylib
.lookup>('hello_world')
.asFunction();
dart
void hello_world();
Slide 46
Slide 46 text
C interoperability
46
● hello_world.dart
import 'dart:ffi';
final dylib = DynamicLibrary.open('$root/mylib/lib/custom.1.0.0.dylib');
final helloWorld = dylib.lookupFunction("hello_world");
dart
Slide 47
Slide 47 text
C interoperability
47
● calc.c #include
#include "calc.h"
int add(int a, int b)
{
return a + b;
}
int subtract(int a, int b)
{
return a - b;
}
C&C++
Slide 48
Slide 48 text
C interoperability
48
● calc.dart
final adder = dylib.lookupFunction('add');
final result = adder(40, 2);
print(result);
dart
int add(int a, int b);
Slide 49
Slide 49 text
C interoperability
49
● calc.dart
final adder = dylib.lookupFunction('add');
final result = adder(40, 2);
print(result);
dart
int add(int a, int b);
Slide 50
Slide 50 text
C interoperability
50
● calc.dart
final adder = dylib.lookupFunction('add');
final result = adder(40, 2);
print(result);
dart
int add(int a, int b);
Slide 51
Slide 51 text
C interoperability
51
● calc.dart
final adder = dylib.lookupFunction('add');
final result = adder(40, 2);
print(result);
dart
int add(int a, int b);
Slide 52
Slide 52 text
C interoperability
52
● calc.dart
final adder = dylib.lookupFunction('add');
final result = adder(40, 2);
print(result);
dart
int add(int a, int b);
Slide 53
Slide 53 text
C interoperability
53
Unhandled exception:
Invalid argument(s): Failed to load dynamic library
(mach-o file, but is an incompatible architecture
(have 'x86_64', need 'arm64'))
Slide 54
Slide 54 text
C interoperability
54
cmake . -DCMAKE_OSX_ARCHITECTURES=arm64
Unhandled exception:
Invalid argument(s): Failed to load dynamic library
(mach-o file, but is an incompatible architecture (have
'x86_64', need 'arm64'))
Slide 55
Slide 55 text
난이도를 조금
올려보겠습니다
55
Slide 56
Slide 56 text
Quiz
56
void main(){
int arr[] = {10, 11, 12, 13, 14};
int *p;
p = arr;
printf("%d \n", *(p + 2));
printf("%d \n", *arr);
}
출력 결과는?
Slide 57
Slide 57 text
C interoperability
57
int subtract(int *a, int b)
{
return *a - b;
}
int *multiply(int a, int b)
{
int *mult = (int *)malloc(sizeof(int));
*mult = a * b;
return mult;
}
C&C++
int subtract(int *a, int b);
int *multiply(int a, int b);
Slide 58
Slide 58 text
C interoperability
58
int subtract(int *a, int b)
{
return *a - b;
}
int *multiply(int a, int b)
{
int *mult = (int *)malloc(sizeof(int));
*mult = a * b;
return mult;
}
C&C++
int subtract(int *a, int b);
int *multiply(int a, int b);
Slide 59
Slide 59 text
C interoperability
59
● pointer.dart
// C subtract function - int subtract(int *a, int b);
typedef SubtractFunc = Int32 Function(Pointer a, Int32 b);
typedef Subtract = int Function(Pointer a, int b);
final subtractPointer =
dylib.lookup>('subtract');
final subtract = subtractPointer.asFunction();
dart
Slide 60
Slide 60 text
C interoperability
60
● pointer.dart
// C subtract function - int subtract(int *a, int b);
typedef SubtractFunc = Int32 Function(Pointer a, Int32 b);
typedef Subtract = int Function(Pointer a, int b);
final subtractPointer =
dylib.lookup>('subtract');
final subtract = subtractPointer.asFunction();
dart
Slide 61
Slide 61 text
C interoperability
61
● pointer.dart
// C subtract function - int subtract(int *a, int b);
typedef SubtractFunc = Int32 Function(Pointer a, Int32 b);
typedef Subtract = int Function(Pointer a, int b);
final subtractPointer =
dylib.lookup>('subtract');
final subtract = subtractPointer.asFunction();
dart
Slide 62
Slide 62 text
C interoperability
62
● pointer.dart
import 'package:ffi/ffi.dart';
dart
Utilities for working with
Foreign Function Interface
(FFI) code.
https://pub.dev/packages/ffi
Slide 63
Slide 63 text
C interoperability
63
● pointer.dart
import 'package:ffi/ffi.dart';
final p = calloc();
p.value = 3;
print('3 - 5 = ${subtract(p, 5)}');
calloc.free(p);
dart
Slide 64
Slide 64 text
C interoperability
64
● pointer.dart
import 'package:ffi/ffi.dart';
final p = calloc();
p.value = 3;
print('3 - 5 = ${subtract(p, 5)}');
calloc.free(p);
dart
const CallocAllocator calloc = CallocAllocator._();
final class CallocAllocator implements Allocator {
const CallocAllocator._();
Slide 65
Slide 65 text
C interoperability
65
● pointer.dart
import 'package:ffi/ffi.dart';
final p = calloc();
p.value = 3;
print('3 - 5 = ${subtract(p, 5)}');
calloc.free(p);
dart
Slide 66
Slide 66 text
C interoperability
66
● pointer.dart
import 'package:ffi/ffi.dart';
final p = calloc();
p.value = 3;
print('3 - 5 = ${subtract(p, 5)}');
calloc.free(p);
dart
Slide 67
Slide 67 text
C interoperability
67
Slide 68
Slide 68 text
C interoperability
68
● main.go package main
import "C"
import "fmt"
//export PrintHello
func PrintHello() {
fmt.Print("Hello,World")
}
func main() {
PrintHello()
}
go
Slide 69
Slide 69 text
C interoperability
69
● main.go
import "C"
import "fmt"
//export PrintHello
func PrintHello() {
fmt.Print("Hello,World")
}
func main() {
PrintHello()
}
go
go build -o libhello.so
-buildmode=c-shared
main.go
Slide 70
Slide 70 text
C interoperability
70
● main.go
import "C"
import "fmt"
//export PrintHello
func PrintHello() {
fmt.Print("Hello,World")
}
func main() {
PrintHello()
}
go
go build -o libhello.so
-buildmode=c-shared
main.go
Slide 71
Slide 71 text
C interoperability
71
● main.go
import "C"
import "fmt"
//export PrintHello
func PrintHello() {
fmt.Print("Hello,World")
}
func main() {
PrintHello()
}
go
go build -o libhello.so
-buildmode=c-shared
main.go