├── .gitignore ├── Cargo.toml ├── cbindgen-ios.toml ├── platform ├── android │ ├── .gitignore │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── krupitskas │ │ │ │ └── pong │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── krupitskas │ │ │ │ │ └── pong │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── RustBindings.java │ │ │ └── res │ │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── drawable │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── krupitskas │ │ │ └── pong │ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle └── ios │ ├── greetings.xcodeproj │ └── project.pbxproj │ └── greetings │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Greetings-Bridging-Header.h │ ├── Info.plist │ ├── RustGreetings.swift │ ├── SceneDelegate.swift │ └── ViewController.swift ├── readme.md ├── sdk.png └── src ├── android ├── fractal.rs └── graphic.rs ├── lib.rs └── pc_main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | build/ 3 | tmp/ 4 | .idea/ 5 | Cargo.lock 6 | *.log 7 | xcuserdata/ 8 | project.xcworkspace/ 9 | /target 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pong" 3 | version = "0.0.1" 4 | authors = ["Nikita Krupitskas "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | [target.'cfg(target_os="android")'.dependencies] 9 | jni = "0.21" 10 | image = "0.24" 11 | num-complex = "0.4" 12 | 13 | [lib] 14 | path = "src/lib.rs" 15 | name = "pong_lib" 16 | crate-type = ["staticlib", "cdylib", "lib"] 17 | 18 | [[bin]] 19 | name = "pong_pc" 20 | path = "src/pc_main.rs" 21 | -------------------------------------------------------------------------------- /cbindgen-ios.toml: -------------------------------------------------------------------------------- 1 | [export] 2 | include = ["rust_greeting", "rust_greeting_free"] 3 | exclude = ["Java_com_krupitskas_pong_RustBindings_greeting", "Java_com_krupitskas_pong_RustBindings_renderFractal", "bitmap_get_info", "bitmap_lock_pixels", "bitmap_unlock_pixels"] 4 | -------------------------------------------------------------------------------- /platform/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | /.idea/* 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | -------------------------------------------------------------------------------- /platform/android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /platform/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | namespace 'com.krupitskas.pong' 5 | compileSdkVersion 33 6 | buildToolsVersion "31.0.0" 7 | ndkVersion '25.1.8937393' 8 | 9 | defaultConfig { 10 | applicationId "com.krupitskas.pong" 11 | minSdkVersion 21 12 | targetSdkVersion 33 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | apply plugin: 'org.mozilla.rust-android-gradle.rust-android' 27 | 28 | cargo { 29 | module = "../../../" 30 | libname = "pong_lib" 31 | targets = ["arm64", "x86", "x86_64", "arm"] 32 | profile = gradle.startParameter.taskNames.any{it.toLowerCase().contains("release")} ? "release" : "debug" 33 | prebuiltToolchains = true 34 | apiLevel = 21 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: 'libs', include: ['*.jar']) 39 | 40 | implementation 'androidx.appcompat:appcompat:1.4.2' 41 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3' 42 | testImplementation 'junit:junit:4.13.2' 43 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 44 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 45 | } 46 | 47 | preBuild.dependsOn "cargoBuild" 48 | -------------------------------------------------------------------------------- /platform/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /platform/android/app/src/androidTest/java/com/krupitskas/pong/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.krupitskas.pong; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.krupitskas.pong", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /platform/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /platform/android/app/src/main/java/com/krupitskas/pong/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.krupitskas.pong; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.graphics.Bitmap; 6 | import android.os.Bundle; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | public class MainActivity extends AppCompatActivity { 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_main); 15 | 16 | String r = RustBindings.greeting("Android world"); 17 | ((TextView)findViewById(R.id.helloWorldText)).setText(r); 18 | 19 | Bitmap bitmap = Bitmap.createBitmap(800, 800, Bitmap.Config.ARGB_8888); 20 | RustBindings.renderFractal(bitmap); 21 | ImageView imageView = findViewById(R.id.imageView); 22 | imageView.setImageBitmap(bitmap); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /platform/android/app/src/main/java/com/krupitskas/pong/RustBindings.java: -------------------------------------------------------------------------------- 1 | package com.krupitskas.pong; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | public class RustBindings { 6 | static { 7 | System.loadLibrary("pong_lib"); 8 | } 9 | 10 | public static native String greeting(final String pattern); 11 | 12 | public static native void renderFractal(Bitmap bitmap); 13 | } -------------------------------------------------------------------------------- /platform/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 34 | 35 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | 7 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Pong 3 | demo 4 | 5 | -------------------------------------------------------------------------------- /platform/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform/android/app/src/test/java/com/krupitskas/pong/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.krupitskas.pong; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /platform/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | maven { 6 | url "https://plugins.gradle.org/m2/" 7 | } 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.3.0' 11 | classpath 'org.mozilla.rust-android-gradle:plugin:0.9.3' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | mavenCentral() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /platform/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | android.injected.testOnly=false 21 | -------------------------------------------------------------------------------- /platform/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/platform/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /platform/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Mar 27 09:44:59 MSK 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 7 | -------------------------------------------------------------------------------- /platform/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /platform/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /platform/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='Pong' 2 | include ':app' 3 | -------------------------------------------------------------------------------- /platform/ios/greetings.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B6031C2029F3D01A0072F80A /* libpong_lib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B66C1431278ADBB200E0BB1C /* libpong_lib.a */; }; 11 | B66C141B278AD98300E0BB1C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66C141A278AD98300E0BB1C /* AppDelegate.swift */; }; 12 | B66C141D278AD98300E0BB1C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66C141C278AD98300E0BB1C /* SceneDelegate.swift */; }; 13 | B66C141F278AD98300E0BB1C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66C141E278AD98300E0BB1C /* ViewController.swift */; }; 14 | B66C1422278AD98300E0BB1C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B66C1420278AD98300E0BB1C /* Main.storyboard */; }; 15 | B66C1424278AD98500E0BB1C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66C1423278AD98500E0BB1C /* Assets.xcassets */; }; 16 | B66C1427278AD98500E0BB1C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B66C1425278AD98500E0BB1C /* LaunchScreen.storyboard */; }; 17 | B66C1430278ADB3200E0BB1C /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B66C142F278ADB3200E0BB1C /* libresolv.tbd */; }; 18 | B66C1436278AE02C00E0BB1C /* RustGreetings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66C1435278AE02C00E0BB1C /* RustGreetings.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | B66C1417278AD98300E0BB1C /* greetings.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = greetings.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | B66C141A278AD98300E0BB1C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 24 | B66C141C278AD98300E0BB1C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 25 | B66C141E278AD98300E0BB1C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 26 | B66C1421278AD98300E0BB1C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | B66C1423278AD98500E0BB1C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | B66C1426278AD98500E0BB1C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | B66C1428278AD98500E0BB1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | B66C142F278ADB3200E0BB1C /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; 31 | B66C1431278ADBB200E0BB1C /* libpong_lib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpong_lib.a; path = ../../target/universal/release/libpong_lib.a; sourceTree = ""; }; 32 | B66C1434278ADCB200E0BB1C /* Greetings-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Greetings-Bridging-Header.h"; sourceTree = ""; }; 33 | B66C1435278AE02C00E0BB1C /* RustGreetings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustGreetings.swift; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | B66C1414278AD98300E0BB1C /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | B6031C2029F3D01A0072F80A /* libpong_lib.a in Frameworks */, 42 | B66C1430278ADB3200E0BB1C /* libresolv.tbd in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | B66C140E278AD98300E0BB1C = { 50 | isa = PBXGroup; 51 | children = ( 52 | B66C1419278AD98300E0BB1C /* greetings */, 53 | B66C1418278AD98300E0BB1C /* Products */, 54 | B66C142E278ADB3100E0BB1C /* Frameworks */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | B66C1418278AD98300E0BB1C /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | B66C1417278AD98300E0BB1C /* greetings.app */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | B66C1419278AD98300E0BB1C /* greetings */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | B66C1434278ADCB200E0BB1C /* Greetings-Bridging-Header.h */, 70 | B66C1435278AE02C00E0BB1C /* RustGreetings.swift */, 71 | B66C141A278AD98300E0BB1C /* AppDelegate.swift */, 72 | B66C141C278AD98300E0BB1C /* SceneDelegate.swift */, 73 | B66C141E278AD98300E0BB1C /* ViewController.swift */, 74 | B66C1420278AD98300E0BB1C /* Main.storyboard */, 75 | B66C1423278AD98500E0BB1C /* Assets.xcassets */, 76 | B66C1425278AD98500E0BB1C /* LaunchScreen.storyboard */, 77 | B66C1428278AD98500E0BB1C /* Info.plist */, 78 | ); 79 | path = greetings; 80 | sourceTree = ""; 81 | }; 82 | B66C142E278ADB3100E0BB1C /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | B66C1431278ADBB200E0BB1C /* libpong_lib.a */, 86 | B66C142F278ADB3200E0BB1C /* libresolv.tbd */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | /* End PBXGroup section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | B66C1416278AD98300E0BB1C /* greetings */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = B66C142B278AD98500E0BB1C /* Build configuration list for PBXNativeTarget "greetings" */; 97 | buildPhases = ( 98 | B6031C2129F3D02E0072F80A /* ShellScript */, 99 | B66C1413278AD98300E0BB1C /* Sources */, 100 | B66C1414278AD98300E0BB1C /* Frameworks */, 101 | B66C1415278AD98300E0BB1C /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = greetings; 108 | productName = greetings; 109 | productReference = B66C1417278AD98300E0BB1C /* greetings.app */; 110 | productType = "com.apple.product-type.application"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | B66C140F278AD98300E0BB1C /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | BuildIndependentTargetsInParallel = 1; 119 | LastSwiftUpdateCheck = 1320; 120 | LastUpgradeCheck = 1320; 121 | TargetAttributes = { 122 | B66C1416278AD98300E0BB1C = { 123 | CreatedOnToolsVersion = 13.2.1; 124 | }; 125 | }; 126 | }; 127 | buildConfigurationList = B66C1412278AD98300E0BB1C /* Build configuration list for PBXProject "greetings" */; 128 | compatibilityVersion = "Xcode 13.0"; 129 | developmentRegion = en; 130 | hasScannedForEncodings = 0; 131 | knownRegions = ( 132 | en, 133 | Base, 134 | ); 135 | mainGroup = B66C140E278AD98300E0BB1C; 136 | productRefGroup = B66C1418278AD98300E0BB1C /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | B66C1416278AD98300E0BB1C /* greetings */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXResourcesBuildPhase section */ 146 | B66C1415278AD98300E0BB1C /* Resources */ = { 147 | isa = PBXResourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | B66C1427278AD98500E0BB1C /* LaunchScreen.storyboard in Resources */, 151 | B66C1424278AD98500E0BB1C /* Assets.xcassets in Resources */, 152 | B66C1422278AD98300E0BB1C /* Main.storyboard in Resources */, 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | }; 156 | /* End PBXResourcesBuildPhase section */ 157 | 158 | /* Begin PBXShellScriptBuildPhase section */ 159 | B6031C2129F3D02E0072F80A /* ShellScript */ = { 160 | isa = PBXShellScriptBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | ); 164 | inputFileListPaths = ( 165 | ); 166 | inputPaths = ( 167 | ); 168 | outputFileListPaths = ( 169 | ); 170 | outputPaths = ( 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | shellPath = /bin/bash; 174 | shellScript = "set -e\nPATH=\"$PATH:${HOME}/.cargo/bin\"\nRUST_PROJ=${PROJECT_DIR}/../..\ncd \"${RUST_PROJ}\"\ncargo lipo --release\ncbindgen --config cbindgen-ios.toml -l C -o target/greetings.h\n"; 175 | }; 176 | /* End PBXShellScriptBuildPhase section */ 177 | 178 | /* Begin PBXSourcesBuildPhase section */ 179 | B66C1413278AD98300E0BB1C /* Sources */ = { 180 | isa = PBXSourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | B66C1436278AE02C00E0BB1C /* RustGreetings.swift in Sources */, 184 | B66C141F278AD98300E0BB1C /* ViewController.swift in Sources */, 185 | B66C141B278AD98300E0BB1C /* AppDelegate.swift in Sources */, 186 | B66C141D278AD98300E0BB1C /* SceneDelegate.swift in Sources */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXSourcesBuildPhase section */ 191 | 192 | /* Begin PBXVariantGroup section */ 193 | B66C1420278AD98300E0BB1C /* Main.storyboard */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | B66C1421278AD98300E0BB1C /* Base */, 197 | ); 198 | name = Main.storyboard; 199 | sourceTree = ""; 200 | }; 201 | B66C1425278AD98500E0BB1C /* LaunchScreen.storyboard */ = { 202 | isa = PBXVariantGroup; 203 | children = ( 204 | B66C1426278AD98500E0BB1C /* Base */, 205 | ); 206 | name = LaunchScreen.storyboard; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXVariantGroup section */ 210 | 211 | /* Begin XCBuildConfiguration section */ 212 | B66C1429278AD98500E0BB1C /* Debug */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | CLANG_ANALYZER_NONNULL = YES; 217 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_ENABLE_MODULES = YES; 221 | CLANG_ENABLE_OBJC_ARC = YES; 222 | CLANG_ENABLE_OBJC_WEAK = YES; 223 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 224 | CLANG_WARN_BOOL_CONVERSION = YES; 225 | CLANG_WARN_COMMA = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 228 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 229 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 230 | CLANG_WARN_EMPTY_BODY = YES; 231 | CLANG_WARN_ENUM_CONVERSION = YES; 232 | CLANG_WARN_INFINITE_RECURSION = YES; 233 | CLANG_WARN_INT_CONVERSION = YES; 234 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 235 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 236 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 237 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 238 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 239 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 240 | CLANG_WARN_STRICT_PROTOTYPES = YES; 241 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 242 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 243 | CLANG_WARN_UNREACHABLE_CODE = YES; 244 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 245 | COPY_PHASE_STRIP = NO; 246 | DEBUG_INFORMATION_FORMAT = dwarf; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | ENABLE_TESTABILITY = YES; 249 | GCC_C_LANGUAGE_STANDARD = gnu11; 250 | GCC_DYNAMIC_NO_PIC = NO; 251 | GCC_NO_COMMON_BLOCKS = YES; 252 | GCC_OPTIMIZATION_LEVEL = 0; 253 | GCC_PREPROCESSOR_DEFINITIONS = ( 254 | "DEBUG=1", 255 | "$(inherited)", 256 | ); 257 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 258 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 259 | GCC_WARN_UNDECLARED_SELECTOR = YES; 260 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 261 | GCC_WARN_UNUSED_FUNCTION = YES; 262 | GCC_WARN_UNUSED_VARIABLE = YES; 263 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 264 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 265 | MTL_FAST_MATH = YES; 266 | ONLY_ACTIVE_ARCH = YES; 267 | SDKROOT = iphoneos; 268 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 269 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 270 | }; 271 | name = Debug; 272 | }; 273 | B66C142A278AD98500E0BB1C /* Release */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ALWAYS_SEARCH_USER_PATHS = NO; 277 | CLANG_ANALYZER_NONNULL = YES; 278 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 280 | CLANG_CXX_LIBRARY = "libc++"; 281 | CLANG_ENABLE_MODULES = YES; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_ENABLE_OBJC_WEAK = YES; 284 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 285 | CLANG_WARN_BOOL_CONVERSION = YES; 286 | CLANG_WARN_COMMA = YES; 287 | CLANG_WARN_CONSTANT_CONVERSION = YES; 288 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 289 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 290 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 291 | CLANG_WARN_EMPTY_BODY = YES; 292 | CLANG_WARN_ENUM_CONVERSION = YES; 293 | CLANG_WARN_INFINITE_RECURSION = YES; 294 | CLANG_WARN_INT_CONVERSION = YES; 295 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 296 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 297 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 298 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 299 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 300 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 301 | CLANG_WARN_STRICT_PROTOTYPES = YES; 302 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 303 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 304 | CLANG_WARN_UNREACHABLE_CODE = YES; 305 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 306 | COPY_PHASE_STRIP = NO; 307 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 308 | ENABLE_NS_ASSERTIONS = NO; 309 | ENABLE_STRICT_OBJC_MSGSEND = YES; 310 | GCC_C_LANGUAGE_STANDARD = gnu11; 311 | GCC_NO_COMMON_BLOCKS = YES; 312 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 313 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 314 | GCC_WARN_UNDECLARED_SELECTOR = YES; 315 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 316 | GCC_WARN_UNUSED_FUNCTION = YES; 317 | GCC_WARN_UNUSED_VARIABLE = YES; 318 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 319 | MTL_ENABLE_DEBUG_INFO = NO; 320 | MTL_FAST_MATH = YES; 321 | SDKROOT = iphoneos; 322 | SWIFT_COMPILATION_MODE = wholemodule; 323 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 324 | VALIDATE_PRODUCT = YES; 325 | }; 326 | name = Release; 327 | }; 328 | B66C142C278AD98500E0BB1C /* Debug */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 332 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 333 | CODE_SIGN_IDENTITY = "Apple Development"; 334 | CODE_SIGN_STYLE = Automatic; 335 | CURRENT_PROJECT_VERSION = 1; 336 | DEVELOPMENT_TEAM = ""; 337 | GENERATE_INFOPLIST_FILE = YES; 338 | HEADER_SEARCH_PATHS = ../../target; 339 | INFOPLIST_FILE = greetings/Info.plist; 340 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 341 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 342 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 343 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 344 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 345 | LD_RUNPATH_SEARCH_PATHS = ( 346 | "$(inherited)", 347 | "@executable_path/Frameworks", 348 | ); 349 | LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../../target/universal/release"; 350 | MARKETING_VERSION = 1.0; 351 | PRODUCT_BUNDLE_IDENTIFIER = com.ssrlive.greetings; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | PROVISIONING_PROFILE_SPECIFIER = ""; 354 | SWIFT_EMIT_LOC_STRINGS = YES; 355 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/Greetings/Greetings-Bridging-Header.h"; 356 | SWIFT_VERSION = 5.0; 357 | TARGETED_DEVICE_FAMILY = "1,2"; 358 | }; 359 | name = Debug; 360 | }; 361 | B66C142D278AD98500E0BB1C /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 365 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 366 | CODE_SIGN_IDENTITY = "Apple Development"; 367 | CODE_SIGN_STYLE = Automatic; 368 | CURRENT_PROJECT_VERSION = 1; 369 | DEVELOPMENT_TEAM = ""; 370 | GENERATE_INFOPLIST_FILE = YES; 371 | HEADER_SEARCH_PATHS = ../../target; 372 | INFOPLIST_FILE = greetings/Info.plist; 373 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 374 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 375 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 376 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 377 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 378 | LD_RUNPATH_SEARCH_PATHS = ( 379 | "$(inherited)", 380 | "@executable_path/Frameworks", 381 | ); 382 | LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/../../target/universal/release"; 383 | MARKETING_VERSION = 1.0; 384 | PRODUCT_BUNDLE_IDENTIFIER = com.ssrlive.greetings; 385 | PRODUCT_NAME = "$(TARGET_NAME)"; 386 | PROVISIONING_PROFILE_SPECIFIER = ""; 387 | SWIFT_EMIT_LOC_STRINGS = YES; 388 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/Greetings/Greetings-Bridging-Header.h"; 389 | SWIFT_VERSION = 5.0; 390 | TARGETED_DEVICE_FAMILY = "1,2"; 391 | }; 392 | name = Release; 393 | }; 394 | /* End XCBuildConfiguration section */ 395 | 396 | /* Begin XCConfigurationList section */ 397 | B66C1412278AD98300E0BB1C /* Build configuration list for PBXProject "greetings" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | B66C1429278AD98500E0BB1C /* Debug */, 401 | B66C142A278AD98500E0BB1C /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | B66C142B278AD98500E0BB1C /* Build configuration list for PBXNativeTarget "greetings" */ = { 407 | isa = XCConfigurationList; 408 | buildConfigurations = ( 409 | B66C142C278AD98500E0BB1C /* Debug */, 410 | B66C142D278AD98500E0BB1C /* Release */, 411 | ); 412 | defaultConfigurationIsVisible = 0; 413 | defaultConfigurationName = Release; 414 | }; 415 | /* End XCConfigurationList section */ 416 | }; 417 | rootObject = B66C140F278AD98300E0BB1C /* Project object */; 418 | } 419 | -------------------------------------------------------------------------------- /platform/ios/greetings/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // greetings 4 | // 5 | // Created by user on 2022/1/9. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | if #available(iOS 13.0, *) { 18 | // Code for iOS 13 and later 19 | } else { 20 | // Code for iOS 12 and earlier 21 | 22 | // Create a UIWindow manually 23 | window = UIWindow(frame: UIScreen.main.bounds) 24 | 25 | // Set the root view controller 26 | let viewController = ViewController() 27 | viewController.view.backgroundColor = .white 28 | window?.rootViewController = viewController 29 | 30 | // Make the window visible 31 | window?.makeKeyAndVisible() 32 | } 33 | return true 34 | } 35 | 36 | // MARK: UISceneSession Lifecycle 37 | 38 | @available(iOS 13.0, *) 39 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 40 | // Called when a new scene session is being created. 41 | // Use this method to select a configuration to create the new scene with. 42 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 43 | } 44 | 45 | @available(iOS 13.0, *) 46 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 47 | // Called when the user discards a scene session. 48 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 49 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 50 | } 51 | 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /platform/ios/greetings/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /platform/ios/greetings/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /platform/ios/greetings/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /platform/ios/greetings/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /platform/ios/greetings/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /platform/ios/greetings/Greetings-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Greetings-Bridging-Header.h 3 | // greetings 4 | // 5 | // Created by user on 2022/1/9. 6 | // 7 | 8 | #ifndef Greetings_Bridging_Header_h 9 | #define Greetings_Bridging_Header_h 10 | 11 | #import "greetings.h" 12 | 13 | #endif /* Greetings_Bridging_Header_h */ 14 | -------------------------------------------------------------------------------- /platform/ios/greetings/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | $(PRODUCT_MODULE_NAME).SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /platform/ios/greetings/RustGreetings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RustGreetings.swift 3 | // greetings 4 | // 5 | // Created by user on 2022/1/9. 6 | // 7 | 8 | import Foundation 9 | 10 | class RustGreetings { 11 | func sayHello(to: String) -> String { 12 | let result = rust_greeting(to) 13 | let swift_result = String(cString: result!) 14 | rust_greeting_free(UnsafeMutablePointer(mutating: result)) 15 | return swift_result 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /platform/ios/greetings/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // greetings 4 | // 5 | // Created by user on 2022/1/9. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | @available(iOS 13.0, *) 15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 19 | guard let _ = (scene as? UIWindowScene) else { return } 20 | } 21 | 22 | @available(iOS 13.0, *) 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | @available(iOS 13.0, *) 31 | func sceneDidBecomeActive(_ scene: UIScene) { 32 | // Called when the scene has moved from an inactive state to an active state. 33 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 34 | } 35 | 36 | @available(iOS 13.0, *) 37 | func sceneWillResignActive(_ scene: UIScene) { 38 | // Called when the scene will move from an active state to an inactive state. 39 | // This may occur due to temporary interruptions (ex. an incoming phone call). 40 | } 41 | 42 | @available(iOS 13.0, *) 43 | func sceneWillEnterForeground(_ scene: UIScene) { 44 | // Called as the scene transitions from the background to the foreground. 45 | // Use this method to undo the changes made on entering the background. 46 | } 47 | 48 | @available(iOS 13.0, *) 49 | func sceneDidEnterBackground(_ scene: UIScene) { 50 | // Called as the scene transitions from the foreground to the background. 51 | // Use this method to save data, release shared resources, and store enough scene-specific state information 52 | // to restore the scene back to its current state. 53 | } 54 | 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /platform/ios/greetings/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // greetings 4 | // 5 | // Created by user on 2022/1/9. 6 | // 7 | 8 | import UIKit 9 | 10 | class ViewController: UIViewController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | 15 | let rustGreetings = RustGreetings() 16 | //print("\(rustGreetings.sayHello(to: "world"))") 17 | 18 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 21)) 19 | label.center = CGPoint(x: 160, y: 285) 20 | label.textAlignment = .center 21 | label.text = rustGreetings.sayHello(to: "from iOS") 22 | self.view.addSubview(label) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Rust with Android Studio or Xcode iOS 2 | 3 | 4 | ## Android Studio 5 | 6 | * Android Studio Arctic Fox | 2020.3.1 Patch 2 7 | * Android SDK Platform 31 8 | * Android NDK 24.0.8215888 9 | * Android SDK Build-Tools 31.0.0 10 | * Android SDK Command-line Tools 11 | * Android SDK Platform-Tools 12 | 13 | #### Config: Tools >> SDK Manager >> SDK Tools (middle tab): 14 | 15 | ![img](./sdk.png) 16 | 17 | ## Rust 18 | 19 | Install rust on your PC from [rustup](https://rustup.rs), 20 | then add some Android targets (arm64, arm, x86_64, x86) for rust. 21 | ``` 22 | rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android 23 | ``` 24 | Uses [rust-android-gradle](https://github.com/mozilla/rust-android-gradle) plugin, so is built with the command: 25 | ```cli 26 | gradlew cargoBuild 27 | 28 | # build release version 29 | ./gradlew assembleRelease 30 | ``` 31 | 32 | ### Function naming convention 33 | 34 | In `src/lib.rs` you need to name the function according to the following naming convention in order to make it available in `Java`. 35 | 36 | If the _Java_ function is called `greeting` and it is saved in a file named `RustBindings.java` pulled from package `com.krupitskas.pong` then in _Rust_ the function name is: 37 | 38 | | Java | package name | filename | function name | 39 | | :--: | :-----------------: | :----------: | :-----------: | 40 | | Java | com_krupitskas_pong | RustBindings | greeting | 41 | 42 | Which would look like this: 43 | 44 | `Java_com_krupitskas_pong_RustBindings_greeting(...)` 45 | 46 | ## Python 47 | 48 | Install [Python](https://www.python.org/downloads/) on your PC. 49 | 50 | > In `macOS` Monterey 12.3 and above, python was removed by Apple, you must install [Python3](https://www.python.org/downloads/) by yourself, then run this command to make python3 as python. 51 | > ``` 52 | > ln -s -f /usr/local/bin/python3 /usr/local/bin/python 53 | > ``` 54 | 55 | ## iOS 56 | ### Prepare 57 | - macOS / Xcode 58 | - `curl https://sh.rustup.rs -sSf | sh` 59 | - `rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios` 60 | - `cargo install cargo-lipo` 61 | - `cargo install cbindgen` 62 | 63 | ### Automation build script 64 | ```bash 65 | set -e 66 | PATH="$PATH:${HOME}/.cargo/bin" 67 | RUST_PROJ=${PROJECT_DIR}/../.. 68 | cd "${RUST_PROJ}" 69 | cargo lipo --release 70 | cbindgen --config cbindgen-ios.toml -l C -o target/greetings.h 71 | ``` 72 | 73 | ## References 74 | - [Rust Android Gradle Plugin](https://github.com/mozilla/rust-android-gradle) 75 | - [One more plugin to build Rust for Android](https://dev.to/willir/one-more-plugin-to-build-rust-for-android-125h) 76 | - [Cargo NDK for Android projects](https://github.com/willir/cargo-ndk-android-gradle) 77 | - [Running Rust on Android](https://blog.svgames.pl/article/running-rust-on-android) 78 | - [Building and Deploying a Rust library on iOS](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html) 79 | - [Building and Deploying a Rust library on Android](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html) 80 | - [Render Fractal image in Android bitmap with Rust](https://hoangpq.github.io/posts/rust-ndk/) 81 | - [How to Use Rust in iOS Apps](https://www.youtube.com/watch?v=YcL6CXz1vmY) 82 | - [Workshop: Use Rust in iOS Apps](https://github.com/thombles/dw2019rust) 83 | 84 | Done! 85 | -------------------------------------------------------------------------------- /sdk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssrlive/rust_on_android_ios/145ff60e652f6c1c707ab0e1a89ec41101ae5148/sdk.png -------------------------------------------------------------------------------- /src/android/fractal.rs: -------------------------------------------------------------------------------- 1 | extern crate image; 2 | extern crate num_complex; 3 | 4 | pub unsafe fn render<'a>(pixels: &mut [u8], width: u32, height: u32) { 5 | let scale_x = 3.0 / width as f32; 6 | let scale_y = 3.0 / height as f32; 7 | 8 | // Create a new ImgBuf with width: imgx and height: imgy 9 | let mut imgbuf = image::ImageBuffer::new(width, height); 10 | 11 | // Iterate over the coordinates and pixels of the image 12 | for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { 13 | let r = (0.3 * x as f32) as u8; 14 | let b = (0.3 * y as f32) as u8; 15 | *pixel = image::Rgb([r, 0, b]); 16 | } 17 | 18 | // A redundant loop to demonstrate reading image data 19 | for x in 0..width { 20 | for y in 0..height { 21 | let cx = y as f32 * scale_x - 1.5; 22 | let cy = x as f32 * scale_y - 1.5; 23 | 24 | let c = num_complex::Complex::new(-0.4, 0.6); 25 | let mut z = num_complex::Complex::new(cx, cy); 26 | 27 | let mut i = 0; 28 | while i < 255 && z.norm() <= 2.0 { 29 | z = z * z + c; 30 | i += 1; 31 | } 32 | 33 | let pixel = imgbuf.get_pixel_mut(x, y); 34 | let image::Rgb(data) = *pixel; 35 | *pixel = image::Rgb([data[0], i as u8, data[2]]); 36 | } 37 | } 38 | 39 | imgbuf.pixels().enumerate().for_each(|(i, pixel)| { 40 | let idx = 4 * i as usize; 41 | let [r, g, b] = pixel.0; 42 | 43 | pixels[idx] = r; 44 | pixels[idx + 1] = g; 45 | pixels[idx + 2] = b; 46 | pixels[idx + 3] = 255; 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /src/android/graphic.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_int, c_uint, c_void}; 2 | 3 | use jni::sys::jobject; 4 | 5 | #[repr(C)] 6 | #[derive(Debug, Default)] 7 | pub struct AndroidBitmapInfo { 8 | pub width: c_uint, 9 | pub height: c_uint, 10 | pub stride: c_uint, 11 | pub format: c_int, 12 | pub flags: c_uint, 13 | } 14 | 15 | impl AndroidBitmapInfo { 16 | pub fn new() -> Self { 17 | Self { 18 | ..Default::default() 19 | } 20 | } 21 | } 22 | 23 | #[link(name = "jnigraphics", kind = "dylib")] 24 | extern "C" { 25 | #[link_name = "AndroidBitmap_getInfo"] 26 | pub fn bitmap_get_info( 27 | env: *mut jni::sys::JNIEnv, 28 | bmp: jobject, 29 | info: *mut AndroidBitmapInfo, 30 | ) -> c_int; 31 | 32 | #[link_name = "AndroidBitmap_lockPixels"] 33 | pub fn bitmap_lock_pixels( 34 | env: *mut jni::sys::JNIEnv, 35 | bmp: jobject, 36 | pixels: *mut *mut c_void, 37 | ) -> c_int; 38 | 39 | #[link_name = "AndroidBitmap_unlockPixels"] 40 | pub fn bitmap_unlock_pixels(env: *mut jni::sys::JNIEnv, bmp: jobject) -> c_int; 41 | } 42 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::{CStr, CString}; 2 | use std::os::raw::c_char; 3 | 4 | pub fn inner_rust_greeting(to: &str) -> String { 5 | "Rust community: Hello ".to_owned() + to 6 | } 7 | 8 | /// # Safety 9 | #[no_mangle] 10 | pub unsafe extern "C" fn rust_greeting(to: *const c_char) -> *mut c_char { 11 | let c_str = CStr::from_ptr(to); 12 | let recipient = match c_str.to_str() { 13 | Err(_) => "there", 14 | Ok(string) => string, 15 | }; 16 | 17 | CString::new(inner_rust_greeting(recipient)) 18 | .unwrap() 19 | .into_raw() 20 | } 21 | 22 | /// # Safety 23 | #[no_mangle] 24 | pub unsafe extern "C" fn rust_greeting_free(s: *mut c_char) { 25 | if s.is_null() { 26 | return; 27 | } 28 | let _ = CString::from_raw(s); 29 | } 30 | 31 | #[cfg(target_os = "android")] 32 | #[allow(non_snake_case)] 33 | pub mod android { 34 | use self::jni::objects::{JClass, JObject, JString}; 35 | use self::jni::sys::jstring; 36 | use self::jni::JNIEnv; 37 | use super::*; 38 | use std::os::raw::c_void; 39 | 40 | #[no_mangle] 41 | pub unsafe extern "C" fn Java_com_krupitskas_pong_RustBindings_greeting( 42 | mut env: JNIEnv, 43 | _: JClass, 44 | java_pattern: JString, 45 | ) -> jstring { 46 | // Our Java companion code might pass-in "world" as a string, hence the name. 47 | let world = rust_greeting( 48 | env.get_string(&java_pattern) 49 | .expect("invalid pattern string") 50 | .as_ptr(), 51 | ); 52 | // Retake pointer so that we can use it below and allow memory to be freed when it goes out of scope. 53 | let output = env 54 | .new_string(CStr::from_ptr(world).to_str().unwrap()) 55 | .expect("Couldn't create java string!"); 56 | rust_greeting_free(world); 57 | 58 | output.into_raw() 59 | } 60 | 61 | mod fractal; 62 | mod graphic; 63 | 64 | #[no_mangle] 65 | pub unsafe extern "C" fn Java_com_krupitskas_pong_RustBindings_renderFractal( 66 | env: JNIEnv, 67 | _: JClass, 68 | bmp: JObject, 69 | ) { 70 | let mut info = graphic::AndroidBitmapInfo::new(); 71 | let raw_env = env.get_native_interface(); 72 | 73 | let bmp = bmp.into_raw(); 74 | 75 | // Read bitmap info 76 | graphic::bitmap_get_info(raw_env, bmp, &mut info); 77 | let mut pixels = 0 as *mut c_void; 78 | 79 | // Lock pixel for draw 80 | graphic::bitmap_lock_pixels(raw_env, bmp, &mut pixels); 81 | 82 | let pixels = 83 | std::slice::from_raw_parts_mut(pixels as *mut u8, (info.stride * info.height) as usize); 84 | 85 | fractal::render(pixels, info.width as u32, info.height as u32); 86 | graphic::bitmap_unlock_pixels(raw_env, bmp); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/pc_main.rs: -------------------------------------------------------------------------------- 1 | use pong_lib::inner_rust_greeting; 2 | 3 | fn main() { 4 | let info = "from PC"; 5 | println!("{}", inner_rust_greeting(info)); 6 | } 7 | --------------------------------------------------------------------------------