The KPy gradle plugin allows you to write Kotlin/Native code and use it from python.

Overview

KPy Plugin

The KPy gradle plugin allows you to write Kotlin/Native code and use it from python.

Note: Modules built with KPy still require XCode when building on macOS, this is a Kotlin/Native limitation.

Features

Implemented

  • Export Kotlin/Native functions and classes without having to touch the Python API directly
  • Convert between Kotlin and Python types with .toPython() and .toKotlin()
  • Conversions handled mostly automatically
  • Class inheritance mapped to python
  • Generate Python stubs
  • Catch Kotlin exceptions and raise them as Python exceptions

Planned

  • Map enum classes to Python enums
  • Vararg support
  • Generics?

Setup

Change your gradle version to 7.5 (nightly builds only as of writing) Enable the plugin in your build.gradle.kts file:

macosX64("native") hostOs == "Linux" -> linuxX64("native") isMingwX64 -> mingwX64("native") else -> throw GradleException("Host OS is not supported in Kotlin/Native.") } // Optional: Better memory manager nativeTarget.apply { binaries { staticLib { binaryOptions["memoryModel"] = "experimental" freeCompilerArgs += listOf("-Xgc=cms") } } } }">
plugins {
    kotlin("multiplatform") version "1.6.21"  // current compatible version
    id("com.martmists.kpy.kpy-plugin") version "0.3.2"  // Requires Gradle 7.5+
}

kotlin {
    val hostOs = System.getProperty("os.name")
    val isMingwX64 = hostOs.startsWith("Windows")
    // You can rename the target from `native` to something else, 
    // but make sure to also change setup.py to match this change!
    // ARM targets are also supported, but I don't know how to test for them
    val nativeTarget = when {
        hostOs == "Mac OS X" -> macosX64("native")
        hostOs == "Linux" -> linuxX64("native")
        isMingwX64 -> mingwX64("native")
        else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
    }

    // Optional: Better memory manager
    nativeTarget.apply {
        binaries {
            staticLib {
                binaryOptions["memoryModel"] = "experimental"
                freeCompilerArgs += listOf("-Xgc=cms")
            }
        }
    }
}

Use the following setup.py template:

from platform import system
from setuptools import setup, Extension, find_packages
from subprocess import Popen, PIPE

osname = system()
debug = True

if osname == "Linux" or osname == "Darwin":
    gradle_bin = "./gradlew"
else:
    gradle_bin = ".\\gradlew.bat"

# Build the project
proc = Popen([gradle_bin, "build"])
if proc.wait() != 0:
    raise Exception("Build failed")

# Fetch configuration from gradle task
proc = Popen([gradle_bin, "setupMetadata"], stdout=PIPE)
if proc.wait() != 0:
    raise Exception("Failed to fetch metadata")
output = proc.stdout.read().decode()
real_output = output.split("===METADATA START===")[1].split("===METADATA END===")[0]

# Apply the configuration
exec(real_output, globals(), locals())


def snake_case(name):
    return name.replace("-", "_").lower()


def extensions():
    folder = "debugStatic" if debug else "releaseStatic"
    prefix = "_" if has_stubs else ""
    native = Extension(prefix + snake_case(project_name),
                       sources=[f'{build_dir}/generated/ksp/{target}/{target}Main/resources/entrypoint.cpp'],
                       include_dirs=[f"{build_dir}/bin/{target}/{folder}/"],
                       library_dirs=[f"{build_dir}/bin/{target}/{folder}/"],
                       libraries=[snake_case(project_name)])

    return [native]


with open("README.md", "r") as fp:
    long_description = fp.read()


attrs = {}

if has_stubs:
    stub_root = f'{build_dir}/generated/ksp/{target}/{target}Main/resources'
    attrs["packages"] = find_packages(where=stub_root)
    attrs["package_dir"] = {"": stub_root}
else:
    attrs["packages"] = []

    
setup(
    name=snake_case(project_name),
    version=project_version,
    description=long_description,
    ext_modules=extensions(),
    **attrs
)

Configuration

To configure the plugin, you can use the kpy configuration.

/Main/resources/` // Note: these will be overwritten every time you build the project generateStubs = true }">
kpy {
    // Pass properties to setup.py, the exec() command will pass them to the context
    // Note: the second parameter is an expression, and must be valid python.
    metadata("my_key", "'my' + 'value'")  // in setup.py you can now use my_key and it evaluates to 'myvalue'

    // Specify the python version to build against.
    // Currently supported: [3.9, 3.10]
    pyVersion = "3.9"

    // Generate python stubs for the native sources
    // These are stored to `build/generated/ksp//Main/resources/`
    // Note: these will be overwritten every time you build the project
    generateStubs = true
}
You might also like...
An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.
An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.

An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile. 项目架构主要分为原生系统层、Android/iOS业务SDK层、KMM SDK层、KMM业务逻辑SDK层、iOS sdkfra

A server code template using Kotlin, Gradle, and Ktor

This project is a server code template using Kotlin, Gradle, and Ktor. It aims to help you build a service by providing reusable code examples that is likely essential for a server.

Don't write a RecyclerView adapter again. Not even a ViewHolder!

LastAdapter Don't write a RecyclerView adapter again. Not even a ViewHolder! Based on Android Data Binding Written in Kotlin No need to write the adap

This repository is part of a Uni-Project to write a complete Compiler for a subset of Java.

Compiler This repository is part of a Uni-Project to write a complete Compiler for a subset of Java. Features error recovery using context sensitive a

Write a Ghidra Extension without using Java or Eclipse!

Ghidra Extension in Kotlin using IntelliJ IDEA Write a Ghidra Extension without using Java or Eclipse! Setup Hit Use this template at the top of the r

Gradle plugin for simplify Kotlin Multiplatform mobile configurations
Gradle plugin for simplify Kotlin Multiplatform mobile configurations

Mobile Multiplatform gradle plugin This is a Gradle plugin for simple setup of Kotlin Multiplatform mobile Gradle modules. Setup buildSrc/build.gradle

Kotlin Native Xcode Plugin
Kotlin Native Xcode Plugin

Kotlin Native Xcode Support Plugin to facilitate debugging iOS applications using Kotlin Native in Xcode. Defines Kotlin files as source code, with ba

 A Kotlin library providing a simple, high-performance way to use off-heap native memory in JVM applications.
A Kotlin library providing a simple, high-performance way to use off-heap native memory in JVM applications.

native_memory_allocator A library which uses sun.misc.Unsafe to allocate off-heap native memory. Motivation The goal of this project is to provide a s

A Kotlin Multiplatform and Compose template that allows you to easily set up your project targeting: Android, Desktop, and Web

A Kotlin Multiplatform and Compose template that allows you to easily set up your project targeting: Android, Desktop, and Web

Owner
Martmists
Primarily backend/tooling dev, proficient in Python and Kotlin
Martmists
Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.

Codename One - Cross Platform Native Apps with Java or Kotlin Codename One is a mobile first cross platform environment for Java and Kotlin developers

Codename One 1.4k Jan 9, 2023
👋 A common toolkit (utils) ⚒️ built to help you further reduce Kotlin boilerplate code and improve development efficiency. Do you think 'kotlin-stdlib' or 'android-ktx' is not sweet enough? You need this! 🍭

Toolkit [ ?? Work in progress ⛏ ?? ??️ ?? ] Snapshot version: repositories { maven("https://s01.oss.sonatype.org/content/repositories/snapshots") }

凛 35 Jul 23, 2022
kinstall is an easy way to install gradle-based command-line kotlin projects that use the application plugin.

kinstall kinstall is an easy way to install gradle-based command-line kotlin projects that use the application plugin. use First, install kinstall its

david kilmer 0 Apr 24, 2022
💫 A Gradle Plugin to generate your networking code from Swagger

Swagger Gradle Codegen A Gradle plugin to generate networking code from a Swagger spec file. This plugin wraps swagger-codegen, and exposes a configur

Yelp.com 399 Nov 28, 2022
A plugin for Termux to use native Android GUI components from CLI applications.

Termux:GUI This is a plugin for Termux that enables command line programs to use the native android GUI. In the examples directory you can find demo v

null 342 Dec 23, 2022
Plugin for Minecraft Dev projects that allows use BON2 as analog of fg.reobf from ForgeGradle

Bon2Gradle Plugin for Minecraft Dev projects that allows use BON2 as analog of fg.reobf from ForgeGradle. Usage Dependencies Gradle 6.8+ (Provider as

Yaroslav Novitsky 3 Nov 10, 2022
Android MVVM framework write in kotlin, develop Android has never been so fun.

KBinding 中文版 Android MVVM framework write in kotlin, base on anko, simple but powerful. It depends on my another project AutoAdapter(A library for sim

Benny 413 Dec 5, 2022
Healtify is a native android app which allows the user to track the amout of Calories they are consuming

Healtify is a native android app which allows the user to track the amout of Calories they are consuming. It not only tracks the calories but also shows how much of fat, protein and carbs they have consumed and how much they should be doing.

Anindya Ray 9 Aug 20, 2022
A Gradle plugin for Kotlin Multiplatform projects that generate a XCFramework for Apple targets or a FatFramework for iOS targets, and manages the publishing process in a CocoaPod Repository.

KMP Framework Bundler KMP Framework Bundler is a Gradle plugin for Kotlin Multiplatform projects that generate a XCFramework for Apple targets or a Fa

Marco Gomiero 17 Oct 29, 2022