Skip to content

Functions

For binding global and member functions, gen_function and gen_method actions should be used, respectively.

Global functions

Let's take a look at a global function binding example. Here is a sample source codes of it:

/**
 * A global function example.
 * __API__
 * action: gen_function
 * package: globs
 * swift.file: GlobUtils
 * throws: no_throw
 */
int mul(int first, int second);

/**
 * A global function example.
 * __API__
 * action: gen_function
 * package: globs
 * swift.file: GlobUtils
 * throws: no_throw
 * overloading_postfix: Three
 */
int mul(int first, int second, int third);

/**
 * A global function example.
 * __API__
 * action: gen_function
 * package: globs
 * swift.file: GlobUtils
 * throws: no_throw
 */
std::string concat(const std::string& str1, const std::string& str2);

Except for the __API__ tag, we have four variables which are instructions for CppBind. With action: gen_function, we define what should be generated in the target language. package variable indicates the package for generated concat function and file shows the place of the saved file. Notice that we have a prefixed variable file with swift prefix, which means that its value will be used only for generated Swift bindings, and for other languages, default value will be used, i.e., source file name. And finally, variable throws defines what kind of exceptions the concat function can throw. Its value is no_throw which means it does not throw any exception. For more details on variables, see Variable Definitions.

And here is a small code demonstrating usage of the generated bindings:

var mulInt = mul(5, 4)
assert(mulInt == 20)

var mulInt1 = mul(5, 4, 3)
assert(mulInt1 == 60)

var res = concat("Hello ", "Johnny")
assert(res == "Hello Johnny" )
mulInt = mul(5, 4)
assert mulInt == 20

mulInt = mul_three(5, 4, 3)
assert mulInt == 60

res = concat("Hello ", "Johnny")
assert res == "Hello Johnny"
var mulInt = mul(first:5, second: 4)
assert(mulInt == 20)

mulInt = mul(first:5, second: 4, third: 3)
assert(mulInt == 60)

var res = concat(str1: "Hello ", str2: "Johnny")
assert(res == "Hello Johnny")

Let's bind more complex examples like template makePair and max, overloaded concat, etc.

/**
 * A global overloaded function example.
 * __API__
 * action: gen_function
 * package: globs
 * swift.file: GlobUtils
 * throws: no_throw
 */
std::string concat(const std::string& str1, const std::string& str2, const std::string& str3);

/**
 * A global template function example.
 * __API__
 * action: gen_function
 * package: globs
 * swift.file: GlobUtils
 * throws: no_throw
 * template:
 *   T:
 *     - type: int
 *     - type: std::string
 */
template <typename T>
T max(T a, T b) {
   return a < b ? b:a;
}

#include "cxx/enums/color.hpp"

namespace cppbind::example {
    /**
     * A global template function example in namespace.
     * __API__
     * action: gen_function
     * package: globs
     * swift.file: GlobUtils
     * throws: no_throw
     * template:
     *   T:
     *     - type: cppbind::example::Project
     *     - type: cppbind::example::Root
     *   V:
     *     - type: cppbind::example::Project
     * return_value_policy: reference
     */
    template <typename T, typename V>
    std::pair<T*, V*> makePair(T* a, V* b) {
       return std::make_pair(a, b);
    }

    /**
     * __API__
     * action: gen_function
     * package: globs
     * swift.file: GlobUtils
     * throws: no_throw
     */
    std::vector<Color> getVectorColor(std::vector<Color> c);
}

Code using generated functions:

res = concat("Hello ", "Johnny ", "Jane")
assert(res == "Hello Johnny Jane")

// [custom-arg-examples-start]
val greeting = greet("Johnny", "Florida")
assert(greeting == "Hello Johnny from Florida")
// [custom-arg-examples-end]

val maxInt = max(2, 5)
assert(maxInt == 5)
val maxString = max("d", "a")
assert(maxString == "d")

val prj1 = Project("My first project")
val prj2 = Project("My second project")
val pairPrjPrj = makePair(prj1, prj2)
assert(pairPrjPrj.first.title == prj1.title)
assert(pairPrjPrj.second.title == prj2.title)

val root1 = Root("/path/to/root/")
val pairRootPrj = makePair(root1, prj1)
assert(pairRootPrj.first.path == root1.path)
assert(pairRootPrj.second.title == prj1.title)
res = concat1("Hello ", "Johnny ", "Jane")
assert res == "Hello Johnny Jane"

# [custom-arg-examples-start]
greeting = greet("Johnny", "Florida")
assert greeting == "Hello Johnny from Florida"

greeting = greet(person="Bob", hometown="California")
assert greeting == "Hello Bob from California"

# [custom-arg-examples-end]

maxInt = max_int(2, 5)
assert maxInt == 5
maxString = max_string("d", "a")
assert maxString == "d"

prj1 = Project("My first project")
prj2 = Project("My second project")
pairPrjPrj = make_pair_project_project(prj1, prj2)
assert pairPrjPrj[0].title == prj1.title
assert pairPrjPrj[1].title == prj2.title

root1 = Root("/path/to/root/")
pairRootPrj = make_pair_root_project(root1, prj1)
assert pairRootPrj[0].path == root1.path
assert pairRootPrj[1].title == prj1.title
res = concat(str1: "Hello ", str2: "Johnny ", str3: "Jane")
assert(res == "Hello Johnny Jane")

// [custom-arg-examples-start]
let greeting = greet(person: "Johnny", from: "Florida")
assert(greeting == "Hello Johnny from Florida")
// [custom-arg-examples-end]

let maxInt = max(a: 2, b: 5)
assert(maxInt == 5)
let maxString = max(a: "d", b: "a")
assert(maxString == "d")

let prj1 = Project(title: "My first project")
let prj2 = Project(title: "My second project")
let pairPrjPrj = makePair(a: prj1, b: prj2)
assert(Mirror(reflecting: pairPrjPrj).children.count == 2)
assert(pairPrjPrj.0.title == prj1.title)
assert(pairPrjPrj.1.title == prj2.title)

let root1 = Root(path: "/path/to/root/")
let pairRootPrj = makePair(a: root1, b: prj1)
assert(Mirror(reflecting: pairRootPrj).children.count == 2)
assert(pairRootPrj.0.path == root1.path)
assert(pairRootPrj.1.title == prj1.title)

Here we have overloaded concat for Kotlin and Swift, but it's slightly different for Python as there's no overloading in Python. We have two concat, and concat1 in Python for C++ concat functions with 2 and 3 arguments respectively. Similarly, we have an overloaded function for each template combination in Kotlin and Swift. In the case of Python, a postfix generated from argument types is appended to the function name.

Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 09/15/2022-11:26.
 * Please do not change it manually.
 */

package com.examples.globs

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
import com.examples.enums.Color
import com.examples.simple.Project
import com.examples.simple.Root

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

/**
 * A global function example.
 */
fun mul(first: Int, second: Int): Int {
    val result = jMul(first, second)

    return result
}

/**
 * A global function example.
 */
fun mul(first: Int, second: Int, third: Int): Int {
    val result = jMulThree(first, second, third)

    return result
}

/**
 * A global function example.
 */
fun concat(str1: String, str2: String): String {
    val result = jConcat(str1, str2)

    return result
}

/**
 * A global overloaded function example.
 */
fun concat(str1: String, str2: String, str3: String): String {
    val result = jConcat1(str1, str2, str3)

    return result
}

/**
 * A global template function example.
 */
fun max(a: Int, b: Int): Int {
    val result = jMaxInt(a, b)

    return result
}

/**
 * A global template function example.
 */
fun max(a: String, b: String): String {
    val result = jMaxString(a, b)

    return result
}

/**
 * A global template function example in namespace.
 */
fun makePair(a: Project, b: Project): Pair<Project, Project> {
    val kotlintojdka = a.cppbindObjId
    val kotlintojdkb = b.cppbindObjId
    val result = jMakepairProjectProject(kotlintojdka, kotlintojdkb, a, b)
    val firstResult = result.first
    val secondResult = result.second
    val jdktokotlinfirstResult = Project(CppBindObject(firstResult))
    val jdktokotlinsecondResult = Project(CppBindObject(secondResult))
    val jdktokotlinresult = Pair<Project, Project>(jdktokotlinfirstResult, jdktokotlinsecondResult)
    return jdktokotlinresult
}

/**
 * A global template function example in namespace.
 */
fun makePair(a: Root, b: Project): Pair<Root, Project> {
    val kotlintojdka = a.cppbindObjId
    val kotlintojdkb = b.cppbindObjId
    val result = jMakepairRootProject(kotlintojdka, kotlintojdkb, a, b)
    val firstResult = result.first
    val secondResult = result.second
    val jdktokotlinfirstResult = Root(CppBindObject(firstResult))
    val jdktokotlinsecondResult = Project(CppBindObject(secondResult))
    val jdktokotlinresult = Pair<Root, Project>(jdktokotlinfirstResult, jdktokotlinsecondResult)
    return jdktokotlinresult
}

fun getVectorColor(c: List<Color>): List<Color> {
    val kotlintojdkc = IntArray(c.size) 
    var indexC = 0
    for (valueC in c) {
        val kotlintojdkvalueC = valueC.value
        kotlintojdkc[indexC] = kotlintojdkvalueC
        ++indexC
    }
    val result = jGetvectorcolor(kotlintojdkc, c)
    val jdktokotlinresult: MutableList<Color> = mutableListOf()
    for (valueResult in result) {
        val jdktokotlinvalueResultOptional = Color.getByValue(valueResult)
        if (jdktokotlinvalueResultOptional == null) {
            ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of Color enum.")
        }
        val jdktokotlinvalueResult = jdktokotlinvalueResultOptional!!
        jdktokotlinresult.add(jdktokotlinvalueResult)
    }
    return jdktokotlinresult
}

/**
 * A global function with pointer default value and nullable return value.
 */
fun optionalFDPtr(project: Project? = null): Project? {
    val kotlintojdkproject = project?.cppbindObjId ?: 0L
    val result = jOptionalfdptr(kotlintojdkproject, project)
    val jdktokotlinresult = if (result == 0L) null else Project(CppBindObject(result))
    return jdktokotlinresult
}

/**
 * A global function with no return value.
 */
fun doNothing(): Unit {
    val result = jDonothing()

    return result
}

private external fun jMul(first: Int, second: Int, vararg extraObjs: Any?): Int
private external fun jMulThree(first: Int, second: Int, third: Int, vararg extraObjs: Any?): Int
private external fun jConcat(str1: String, str2: String, vararg extraObjs: Any?): String
private external fun jConcat1(str1: String, str2: String, str3: String, vararg extraObjs: Any?): String
private external fun jMaxInt(a: Int, b: Int, vararg extraObjs: Any?): Int
private external fun jMaxString(a: String, b: String, vararg extraObjs: Any?): String
private external fun jMakepairProjectProject(a: Long, b: Long, vararg extraObjs: Any?): Pair<Long, Long>
private external fun jMakepairRootProject(a: Long, b: Long, vararg extraObjs: Any?): Pair<Long, Long>
private external fun jGetvectorcolor(c: IntArray, vararg extraObjs: Any?): IntArray
private external fun jOptionalfdptr(project: Long, vararg extraObjs: Any?): Long
private external fun jDonothing(): Unit

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 11/24/2022-07:17.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.globs.utils as pybind_utils_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *

if TYPE_CHECKING:
    import examples_lib.enums.color_pygen as enums_color_pygen
    import examples_lib.simple.project_pygen as simple_project_pygen
    import examples_lib.simple.root_pygen as simple_root_pygen


@bind
def mul(first: int, second: int) -> int:
    """
    A global function example.
    """
    pass


@bind
def mul_three(first: int, second: int, third: int) -> int:
    """
    A global function example.
    """
    pass


@bind
def concat(str1: str, str2: str) -> str:
    """
    A global function example.
    """
    pass


@bind
def concat1(str1: str, str2: str, str3: str) -> str:
    """
    A global overloaded function example.
    """
    pass


@bind
def max_int(a: int, b: int) -> int:
    """
    A global template function example.
    """
    pass


@bind
def max_string(a: str, b: str) -> str:
    """
    A global template function example.
    """
    pass


@bind
def make_pair_project_project(a: simple_project_pygen.Project, b: simple_project_pygen.Project) -> Tuple[simple_project_pygen.Project, simple_project_pygen.Project]:
    """
    A global template function example in namespace.
    """
    pass


@bind
def make_pair_root_project(a: simple_root_pygen.Root, b: simple_project_pygen.Project) -> Tuple[simple_root_pygen.Root, simple_project_pygen.Project]:
    """
    A global template function example in namespace.
    """
    pass


@bind
def get_vector_color(c: List[enums_color_pygen.Color]) -> List[enums_color_pygen.Color]:

    pass


@bind
def optional_f_d_ptr(project: Optional[simple_project_pygen.Project] = None) -> Optional[simple_project_pygen.Project]:
    """
    A global function with pointer default value and nullable return value.
    """
    pass


@bind
def do_nothing() -> None:
    """
    A global function with no return value.
    """
    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 09/15/2022-14:11.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// A global function example.
public func mul(first: Int, second: Int) -> Int {
  let swifttoscfirst = CInt(first)
  let swifttoscsecond = CInt(second)
  var cppbindErr = CppBindCObject()
  let result = _func__mul(swifttoscfirst, swifttoscsecond, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = Int(result)
  return sctoswiftresult
}

/// A global function example.
public func mul(first: Int, second: Int, third: Int) -> Int {
  let swifttoscfirst = CInt(first)
  let swifttoscsecond = CInt(second)
  let swifttoscthird = CInt(third)
  var cppbindErr = CppBindCObject()
  let result = _func__mulThree(swifttoscfirst, swifttoscsecond, swifttoscthird, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = Int(result)
  return sctoswiftresult
}

/// A global function example.
public func concat(str1: String, str2: String) -> String {
  let swifttoscstr1 = strdup(str1)!
  let swifttoscstr2 = strdup(str2)!
  var cppbindErr = CppBindCObject()
  let result = _func__concat(swifttoscstr1, swifttoscstr2, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global overloaded function example.
public func concat(str1: String, str2: String, str3: String) -> String {
  let swifttoscstr1 = strdup(str1)!
  let swifttoscstr2 = strdup(str2)!
  let swifttoscstr3 = strdup(str3)!
  var cppbindErr = CppBindCObject()
  let result = _func__concat1(swifttoscstr1, swifttoscstr2, swifttoscstr3, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global template function example.
public func max(a: Int, b: Int) -> Int {
  let swifttosca = CInt(a)
  let swifttoscb = CInt(b)
  var cppbindErr = CppBindCObject()
  let result = _func__maxInt(swifttosca, swifttoscb, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = Int(result)
  return sctoswiftresult
}

/// A global template function example.
public func max(a: String, b: String) -> String {
  let swifttosca = strdup(a)!
  let swifttoscb = strdup(b)!
  var cppbindErr = CppBindCObject()
  let result = _func__maxString(swifttosca, swifttoscb, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global template function example in namespace.
public func makePair(a: Project, b: Project) -> (Project, Project) {
  let swifttosca = a.cself
  let swifttoscb = b.cself
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_makePairProjectProject(swifttosca, swifttoscb, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let _resultFirstData = UnsafeBufferPointer<CppBindCObject>(
    start: result.first.assumingMemoryBound(to: CppBindCObject.self),
    count: 1)
  let _resultSecondData = UnsafeBufferPointer<CppBindCObject>(
    start: result.second.assumingMemoryBound(to: CppBindCObject.self),
    count: 1)
  defer {
    _resultFirstData.deallocate()
    _resultSecondData.deallocate()
  }
  let resultFirst = _resultFirstData[0]
  let resultSecond = _resultSecondData[0]
  var sctoswiftresultFirst: Project
  sctoswiftresultFirst = Project(resultFirst)
  var sctoswiftresultSecond: Project
  sctoswiftresultSecond = Project(resultSecond)
  let sctoswiftresult: (Project, Project) = (sctoswiftresultFirst, sctoswiftresultSecond)
  return sctoswiftresult
}

/// A global template function example in namespace.
public func makePair(a: Root, b: Project) -> (Root, Project) {
  let swifttosca = a.cself
  let swifttoscb = b.cself
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_makePairRootProject(swifttosca, swifttoscb, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let _resultFirstData = UnsafeBufferPointer<CppBindCObject>(
    start: result.first.assumingMemoryBound(to: CppBindCObject.self),
    count: 1)
  let _resultSecondData = UnsafeBufferPointer<CppBindCObject>(
    start: result.second.assumingMemoryBound(to: CppBindCObject.self),
    count: 1)
  defer {
    _resultFirstData.deallocate()
    _resultSecondData.deallocate()
  }
  let resultFirst = _resultFirstData[0]
  let resultSecond = _resultSecondData[0]
  var sctoswiftresultFirst: Root
  sctoswiftresultFirst = Root(resultFirst)
  var sctoswiftresultSecond: Project
  sctoswiftresultSecond = Project(resultSecond)
  let sctoswiftresult: (Root, Project) = (sctoswiftresultFirst, sctoswiftresultSecond)
  return sctoswiftresult
}

public func getVectorColor(c: Array<Color>) -> Array<Color> {
  let _swifttosccData = UnsafeMutablePointer<CInt>.allocate(capacity: c.count)
  var swifttoscc = CppBindCDataArray()
  swifttoscc.data = UnsafeMutableRawPointer(_swifttosccData)
  swifttoscc.size = Int64(c.count)
  for i in 0..<c.count {
    let cVal = c[i]
    let swifttosccVal = cVal.rawValue
    _swifttosccData[i] = swifttosccVal
  }
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExample_getVectorColor(swifttoscc, &cppbindErr)

  swifttoscc.data.deallocate()
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let _resultBuffer = UnsafeBufferPointer<CInt>(
    start: result.data.assumingMemoryBound(to: CInt.self),
    count: Int(result.size))
  var sctoswiftresult: [Color] = []
  defer {
    _resultBuffer.deallocate()
  }
  for i in 0..<Int(result.size) {
    let resultValue = _resultBuffer[i]
    guard let sctoswiftresultValue = Color(rawValue: resultValue) else {
       ExceptionHandler.handleUncaughtException(
          "Internal error: unresolved reference to non existing field of Color enum.")
    }
    sctoswiftresult.append(sctoswiftresultValue)
  }
  return sctoswiftresult
}

/// A global function with pointer default value and nullable return value.
public func optionalFDPtr(project: Project? = nil) -> Project? {
  let swifttoscproject = project?.cself ?? CppBindCObject(type: nil, ptr: nil)
  var cppbindErr = CppBindCObject()
  let result = _func__optionalFDPtr(swifttoscproject, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  var sctoswiftresult: Project? = nil
  if (result.ptr != nil) {
    sctoswiftresult = Project(result)
  }
  return sctoswiftresult
}

/// A global function with no return value.
public func doNothing() -> Void {
  var cppbindErr = CppBindCObject()
  _func__doNothing(&cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
}

Overloaded methods

Let's now bind a struct with overloaded methods:

/**
 * Sum two ints.
 * __API__
 * action: gen_method
 * throws: no_throw
 */
static int sum(int first, int second) {
    return first + second;
}

/**
 * Sum two floats.
 * __API__
 * action: gen_method
 * throws: no_throw
 */
static float sum(float first, float second) {
    return first + second;
}

/**
 * Concatenate with two strings.
 * __API__
 * action: gen_method
 * throws: no_throw
 */
std::string concatenate(std::string first, std::string second) {
    return first + second;
}

/**
 * Concatenate with three strings.
 * __API__
 * action: gen_method
 * throws: no_throw
 */
std::string concatenate(std::string first, std::string second, std::string third) {
    return first + second + third;
}

As you can see, overloaded methods are like regular methods. There's nothing special to add to the API for them.

Note

Python does not have method overloading, but we have overloaded sum and concatenate methods in this case, with some tricks under the hood.

We are ready to use the generated bindings:

assert(Utils.sum(1, 2) == 3)
assert(Utils.sum(2.0f, 3.0f) == 5.0f)
val utils = Utils()
assert(utils.concatenate("1", "2") == "12")
assert(utils.concatenate("a", "b", "c") == "abc")
assert Utils.sum(1, 2) == 3
assert Utils.sum(2.0, 3.0) == 5.0

utils = Utils()
assert utils.concatenate("1", "2") == "12"
assert utils.concatenate("a", "b", "c") == "abc"
assert(Utils.sum(first: 1, second: 2) == 3)
assert(Utils.sum(first: 2.0, second: 3.0) == 5.0)

let utils = Utils()
assert(utils.concatenate(first: "1", second: "2") == "12")
assert(utils.concatenate(first: "a", second: "b", third: "c") == "abc")
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/18/2022-11:02.
 * Please do not change it manually.
 */

package com.examples.overloads

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

/**
 * An example with overloaded methods.
 */
open class Utils
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        /**
         * Sum two ints.
         */
        fun sum(first: Int, second: Int): Int {
            val result = jSum(first, second)

            return result
        }
        @JvmStatic
        private external fun jSum(first: Int, second: Int, vararg extraObjs: Any?): Int

        /**
         * Sum two floats.
         */
        fun sum(first: Float, second: Float): Float {
            val result = jSum1(first, second)

            return result
        }
        @JvmStatic
        private external fun jSum1(first: Float, second: Float, vararg extraObjs: Any?): Float

        /**
         * Sub two ints.
         */
        fun minus(first: Int, second: Int): Int {
            val result = jMinus(first, second)

            return result
        }
        @JvmStatic
        private external fun jMinus(first: Int, second: Int, vararg extraObjs: Any?): Int

        /**
         * Sub two floats.
         */
        fun minus(first: Float, second: Float): Float {
            val result = jMinus1(first, second)

            return result
        }
        @JvmStatic
        private external fun jMinus1(first: Float, second: Float, vararg extraObjs: Any?): Float
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Utils"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    /**
     * Concatenate with two strings.
     */
    fun concatenate(first: String, second: String): String {
        val result = jConcatenate(cppbindObjId, first, second)

        return result
    }

    /**
     * Concatenate with three strings.
     */
    fun concatenate(first: String, second: String, third: String): String {
        val result = jConcatenate1(cppbindObjId, first, second, third)

        return result
    }

    @JvmName("sum2")
    fun sum(first: List<Int>, second: List<Int>): List<Int> {
        val kotlintojdkfirst = IntArray(first.size) 
        var indexFirst = 0
        for (valueFirst in first) {

            kotlintojdkfirst[indexFirst] = valueFirst
            ++indexFirst
        }
        val kotlintojdksecond = IntArray(second.size) 
        var indexSecond = 0
        for (valueSecond in second) {

            kotlintojdksecond[indexSecond] = valueSecond
            ++indexSecond
        }
        val result = jSum2(cppbindObjId, kotlintojdkfirst, kotlintojdksecond, first, second)
        val jdktokotlinresult: MutableList<Int> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    @JvmName("sum3")
    fun sum(first: List<Float>, second: List<Float>): List<Float> {
        val kotlintojdkfirst = FloatArray(first.size) 
        var indexFirst = 0
        for (valueFirst in first) {

            kotlintojdkfirst[indexFirst] = valueFirst
            ++indexFirst
        }
        val kotlintojdksecond = FloatArray(second.size) 
        var indexSecond = 0
        for (valueSecond in second) {

            kotlintojdksecond[indexSecond] = valueSecond
            ++indexSecond
        }
        val result = jSum3(cppbindObjId, kotlintojdkfirst, kotlintojdksecond, first, second)
        val jdktokotlinresult: MutableList<Float> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Utils
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    override fun close() {
        if (cppbindObj.owner && cppbindObj.id != 0L) {
            jFinalize(cppbindObj.id)
            cppbindObj.id = 0L
        }
    }

    /**
     * Finalize and deletes the object
     */
    protected fun finalize() {
        close()
    }

    ///// External wrapper functions ////////////
    private external fun jConcatenate(id: Long, first: String, second: String, vararg extraObjs: Any?): String
    private external fun jConcatenate1(id: Long, first: String, second: String, third: String, vararg extraObjs: Any?): String
    private external fun jSum2(id: Long, first: IntArray, second: IntArray, vararg extraObjs: Any?): IntArray
    private external fun jSum3(id: Long, first: FloatArray, second: FloatArray, vararg extraObjs: Any?): FloatArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.overloads.utils as pybind_utils_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class Utils(metaclass=CppBindMetaclass):
    """
    An example with overloaded methods.
    """

    @bind
    def __init__(self):

        pass

    @classmethod
    @bind
    def sum(cls, first: int, second: int) -> int:
        """
        Sum two ints.
        """
        pass

    @classmethod
    @bind
    def sum(cls, first: float, second: float) -> float:
        """
        Sum two floats.
        """
        pass

    @bind
    def concatenate(self, first: str, second: str) -> str:
        """
        Concatenate with two strings.
        """
        pass

    @bind
    def concatenate(self, first: str, second: str, third: str) -> str:
        """
        Concatenate with three strings.
        """
        pass

    @classmethod
    @bind
    def minus(cls, first: int, second: int) -> int:
        """
        Sub two ints.
        """
        pass

    @classmethod
    @bind
    def minus(cls, first: float, second: float) -> float:
        """
        Sub two floats.
        """
        pass

    @bind
    def sum_lists(self, first: List[int], second: List[int]) -> List[int]:

        pass

    @bind
    def sum_lists(self, first: List[float], second: List[float]) -> List[float]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:59.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// An example with overloaded methods.
public class Utils {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  public let owner: Bool
  private var refs: [Any]

  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    self.cself = _cself
    self.owner = _owner
    self.refs = []
  }

  deinit {
    release_CppbindExample_Utils(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Utils(&cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  /// Sum two ints.
  public static func sum(first: Int, second: Int) -> Int {

    let swifttoscfirst = CInt(first)
    let swifttoscsecond = CInt(second)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  /// Sum two floats.
  public static func sum(first: Float, second: Float) -> Float {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum1(first, second, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    return result
  }

  /// Concatenate with two strings.
  public func concatenate(first: String, second: String) -> String {

    let swifttoscfirst = strdup(first)!
    let swifttoscsecond = strdup(second)!
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_concatenate(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = String(cString: result)
    defer {
      result.deallocate()
    }
    return sctoswiftresult
  }

  /// Concatenate with three strings.
  public func concatenate(first: String, second: String, third: String) -> String {

    let swifttoscfirst = strdup(first)!
    let swifttoscsecond = strdup(second)!
    let swifttoscthird = strdup(third)!
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_concatenate1(cself, swifttoscfirst, swifttoscsecond, swifttoscthird, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = String(cString: result)
    defer {
      result.deallocate()
    }
    return sctoswiftresult
  }

  /// Sub two ints.
  public static func minus(first: Int, second: Int) -> Int {

    let swifttoscfirst = CInt(first)
    let swifttoscsecond = CInt(second)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_minus(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  /// Sub two floats.
  public static func minus(first: Float, second: Float) -> Float {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_minus1(first, second, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    return result
  }

  public func sum(first: Array<Int>, second: Array<Int>) -> Array<Int> {

    let _swifttoscfirstData = UnsafeMutablePointer<CInt>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]
      let swifttoscfirstVal = CInt(firstVal)
      _swifttoscfirstData[i] = swifttoscfirstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<CInt>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]
      let swifttoscsecondVal = CInt(secondVal)
      _swifttoscsecondData[i] = swifttoscsecondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum2(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let _resultBuffer = UnsafeBufferPointer<CInt>(
      start: result.data.assumingMemoryBound(to: CInt.self),
      count: Int(result.size))
    var sctoswiftresult: [Int] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = Int(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public func sum(first: Array<Float>, second: Array<Float>) -> Array<Float> {

    let _swifttoscfirstData = UnsafeMutablePointer<CFloat>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]

      _swifttoscfirstData[i] = firstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<CFloat>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]

      _swifttoscsecondData[i] = secondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum3(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let _resultBuffer = UnsafeBufferPointer<CFloat>(
      start: result.data.assumingMemoryBound(to: CFloat.self),
      count: Int(result.size))
    var sctoswiftresult: [Float] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]

      sctoswiftresult.append(resultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Utils" }
}

Static methods

The binding mechanism of static methods is similar to the binding of regular methods. Nothing special should be added in API comments:

 /**
 * Sub two ints.
 * __API__
 * action: gen_method
 * name: minus
 * throws: no_throw
 */
static int sub(int first, int second) {
    return first - second;
}

/**
 * Sub two floats.
 * __API__
 * action: gen_method
 * name: minus
 * throws: no_throw
 */
static float sub(float first, float second) {
    return first - second;
}

Here are the usage examples:

assert(Utils.minus(3, 2) == 1)
assert(Utils.minus(7.0f, 3.0f) == 4.0f)
assert Utils.minus(3, 2) == 1
assert Utils.minus(7.0, 3.0) == 4.0
assert(Utils.minus(first: 3, second: 2) == 1)
assert(Utils.minus(first: 7.0, second: 3.0) == 4.0)
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/18/2022-11:02.
 * Please do not change it manually.
 */

package com.examples.overloads

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

/**
 * An example with overloaded methods.
 */
open class Utils
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(): Long {
            val id = jConstructor()
            return id
        }

        @JvmStatic
        private external fun jConstructor(): Long

        /**
         * Sum two ints.
         */
        fun sum(first: Int, second: Int): Int {
            val result = jSum(first, second)

            return result
        }
        @JvmStatic
        private external fun jSum(first: Int, second: Int, vararg extraObjs: Any?): Int

        /**
         * Sum two floats.
         */
        fun sum(first: Float, second: Float): Float {
            val result = jSum1(first, second)

            return result
        }
        @JvmStatic
        private external fun jSum1(first: Float, second: Float, vararg extraObjs: Any?): Float

        /**
         * Sub two ints.
         */
        fun minus(first: Int, second: Int): Int {
            val result = jMinus(first, second)

            return result
        }
        @JvmStatic
        private external fun jMinus(first: Int, second: Int, vararg extraObjs: Any?): Int

        /**
         * Sub two floats.
         */
        fun minus(first: Float, second: Float): Float {
            val result = jMinus1(first, second)

            return result
        }
        @JvmStatic
        private external fun jMinus1(first: Float, second: Float, vararg extraObjs: Any?): Float
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::Utils"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(): this(CppBindObject(constructHelper(), true)) {
    }

    /**
     * Concatenate with two strings.
     */
    fun concatenate(first: String, second: String): String {
        val result = jConcatenate(cppbindObjId, first, second)

        return result
    }

    /**
     * Concatenate with three strings.
     */
    fun concatenate(first: String, second: String, third: String): String {
        val result = jConcatenate1(cppbindObjId, first, second, third)

        return result
    }

    @JvmName("sum2")
    fun sum(first: List<Int>, second: List<Int>): List<Int> {
        val kotlintojdkfirst = IntArray(first.size) 
        var indexFirst = 0
        for (valueFirst in first) {

            kotlintojdkfirst[indexFirst] = valueFirst
            ++indexFirst
        }
        val kotlintojdksecond = IntArray(second.size) 
        var indexSecond = 0
        for (valueSecond in second) {

            kotlintojdksecond[indexSecond] = valueSecond
            ++indexSecond
        }
        val result = jSum2(cppbindObjId, kotlintojdkfirst, kotlintojdksecond, first, second)
        val jdktokotlinresult: MutableList<Int> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    @JvmName("sum3")
    fun sum(first: List<Float>, second: List<Float>): List<Float> {
        val kotlintojdkfirst = FloatArray(first.size) 
        var indexFirst = 0
        for (valueFirst in first) {

            kotlintojdkfirst[indexFirst] = valueFirst
            ++indexFirst
        }
        val kotlintojdksecond = FloatArray(second.size) 
        var indexSecond = 0
        for (valueSecond in second) {

            kotlintojdksecond[indexSecond] = valueSecond
            ++indexSecond
        }
        val result = jSum3(cppbindObjId, kotlintojdkfirst, kotlintojdksecond, first, second)
        val jdktokotlinresult: MutableList<Float> = mutableListOf()
        for (valueResult in result) {

            jdktokotlinresult.add(valueResult)
        }
        return jdktokotlinresult
    }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Utils
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    override fun close() {
        if (cppbindObj.owner && cppbindObj.id != 0L) {
            jFinalize(cppbindObj.id)
            cppbindObj.id = 0L
        }
    }

    /**
     * Finalize and deletes the object
     */
    protected fun finalize() {
        close()
    }

    ///// External wrapper functions ////////////
    private external fun jConcatenate(id: Long, first: String, second: String, vararg extraObjs: Any?): String
    private external fun jConcatenate1(id: Long, first: String, second: String, third: String, vararg extraObjs: Any?): String
    private external fun jSum2(id: Long, first: IntArray, second: IntArray, vararg extraObjs: Any?): IntArray
    private external fun jSum3(id: Long, first: FloatArray, second: FloatArray, vararg extraObjs: Any?): FloatArray
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.overloads.utils as pybind_utils_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class Utils(metaclass=CppBindMetaclass):
    """
    An example with overloaded methods.
    """

    @bind
    def __init__(self):

        pass

    @classmethod
    @bind
    def sum(cls, first: int, second: int) -> int:
        """
        Sum two ints.
        """
        pass

    @classmethod
    @bind
    def sum(cls, first: float, second: float) -> float:
        """
        Sum two floats.
        """
        pass

    @bind
    def concatenate(self, first: str, second: str) -> str:
        """
        Concatenate with two strings.
        """
        pass

    @bind
    def concatenate(self, first: str, second: str, third: str) -> str:
        """
        Concatenate with three strings.
        """
        pass

    @classmethod
    @bind
    def minus(cls, first: int, second: int) -> int:
        """
        Sub two ints.
        """
        pass

    @classmethod
    @bind
    def minus(cls, first: float, second: float) -> float:
        """
        Sub two floats.
        """
        pass

    @bind
    def sum_lists(self, first: List[int], second: List[int]) -> List[int]:

        pass

    @bind
    def sum_lists(self, first: List[float], second: List[float]) -> List[float]:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:59.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// An example with overloaded methods.
public class Utils {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  public let owner: Bool
  private var refs: [Any]

  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    self.cself = _cself
    self.owner = _owner
    self.refs = []
  }

  deinit {
    release_CppbindExample_Utils(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init() {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExample_Utils(&cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  /// Sum two ints.
  public static func sum(first: Int, second: Int) -> Int {

    let swifttoscfirst = CInt(first)
    let swifttoscsecond = CInt(second)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  /// Sum two floats.
  public static func sum(first: Float, second: Float) -> Float {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum1(first, second, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    return result
  }

  /// Concatenate with two strings.
  public func concatenate(first: String, second: String) -> String {

    let swifttoscfirst = strdup(first)!
    let swifttoscsecond = strdup(second)!
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_concatenate(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = String(cString: result)
    defer {
      result.deallocate()
    }
    return sctoswiftresult
  }

  /// Concatenate with three strings.
  public func concatenate(first: String, second: String, third: String) -> String {

    let swifttoscfirst = strdup(first)!
    let swifttoscsecond = strdup(second)!
    let swifttoscthird = strdup(third)!
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_concatenate1(cself, swifttoscfirst, swifttoscsecond, swifttoscthird, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = String(cString: result)
    defer {
      result.deallocate()
    }
    return sctoswiftresult
  }

  /// Sub two ints.
  public static func minus(first: Int, second: Int) -> Int {

    let swifttoscfirst = CInt(first)
    let swifttoscsecond = CInt(second)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_minus(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  /// Sub two floats.
  public static func minus(first: Float, second: Float) -> Float {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_minus1(first, second, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    return result
  }

  public func sum(first: Array<Int>, second: Array<Int>) -> Array<Int> {

    let _swifttoscfirstData = UnsafeMutablePointer<CInt>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]
      let swifttoscfirstVal = CInt(firstVal)
      _swifttoscfirstData[i] = swifttoscfirstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<CInt>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]
      let swifttoscsecondVal = CInt(secondVal)
      _swifttoscsecondData[i] = swifttoscsecondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum2(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let _resultBuffer = UnsafeBufferPointer<CInt>(
      start: result.data.assumingMemoryBound(to: CInt.self),
      count: Int(result.size))
    var sctoswiftresult: [Int] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]
      let sctoswiftresultValue = Int(resultValue)
      sctoswiftresult.append(sctoswiftresultValue)
    }
    return sctoswiftresult
  }

  public func sum(first: Array<Float>, second: Array<Float>) -> Array<Float> {

    let _swifttoscfirstData = UnsafeMutablePointer<CFloat>.allocate(capacity: first.count)
    var swifttoscfirst = CppBindCDataArray()
    swifttoscfirst.data = UnsafeMutableRawPointer(_swifttoscfirstData)
    swifttoscfirst.size = Int64(first.count)
    for i in 0..<first.count {
      let firstVal = first[i]

      _swifttoscfirstData[i] = firstVal
    }
    let _swifttoscsecondData = UnsafeMutablePointer<CFloat>.allocate(capacity: second.count)
    var swifttoscsecond = CppBindCDataArray()
    swifttoscsecond.data = UnsafeMutableRawPointer(_swifttoscsecondData)
    swifttoscsecond.size = Int64(second.count)
    for i in 0..<second.count {
      let secondVal = second[i]

      _swifttoscsecondData[i] = secondVal
    }
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExample_Utils_sum3(cself, swifttoscfirst, swifttoscsecond, &cppbindErr)

    swifttoscfirst.data.deallocate()

    swifttoscsecond.data.deallocate()
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    let _resultBuffer = UnsafeBufferPointer<CFloat>(
      start: result.data.assumingMemoryBound(to: CFloat.self),
      count: Int(result.size))
    var sctoswiftresult: [Float] = []
    defer {
      _resultBuffer.deallocate()
    }
    for i in 0..<Int(result.size) {
      let resultValue = _resultBuffer[i]

      sctoswiftresult.append(resultValue)
    }
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::Utils" }
}

Also, note that CppBind supports static overloaded methods.

Custom argument names and labels

It is possible to specify argument names and argument labels (for Swift only) using argument_name and argument_label variables. Here's an example function where the user explicitly gives the argument name and label for each argument. Those new values will be used in the target language instead of the names they have in C++.

 /** A global function with custom argument name and label.
 * __API__
 * action: gen_function
 * kotlin.package: globs.custom_args
 * package: globs
 * file: customArgUtils
 * throws: no_throw
 * argument_name:
    name: person
 * argument_label:
    hometown: from
 */
std::string greet(const std::string& name, const std::string& hometown);

And here is a small code example using generated bindings:

val greeting = greet("Johnny", "Florida")
assert(greeting == "Hello Johnny from Florida")
greeting = greet("Johnny", "Florida")
assert greeting == "Hello Johnny from Florida"

greeting = greet(person="Bob", hometown="California")
assert greeting == "Hello Bob from California"
let greeting = greet(person: "Johnny", from: "Florida")
assert(greeting == "Hello Johnny from Florida")

Note

If the original function does not have argument names, CppBind will generate argument names using indexing, i.e. arg1, arg2, etc. The users can override this by using generated argument names in the argument_name variable. Here's a small example:

action: gen_function
argument_name:
arg1: input
arg2: output
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/11/2022-09:04.
 * Please do not change it manually.
 */

package com.examples.globs.custom_args

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

/**
 * A global function with custom argument name and label.
 */
fun greet(person: String, hometown: String): String {
    val result = jGreet(person, hometown)

    return result
}

private external fun jGreet(person: String, hometown: String, vararg extraObjs: Any?): String

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.globs.customArgUtils as pybind_customArgUtils_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


@bind
def greet(person: str, hometown: str) -> str:
    """
    A global function with custom argument name and label.
    """
    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:58.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// A global function with custom argument name and label.
public func greet(person: String, from hometown: String) -> String {
  let swifttoscperson = strdup(person)!
  let swifttoschometown = strdup(hometown)!
  var cppbindErr = CppBindCObject()
  let result = _func__greet(swifttoscperson, swifttoschometown, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

Nullable arguments

Let's take a look at the following example:

/**
 * An example with nullable arguments.
 * __API__
 * action: gen_class
 * shared_ref: true
 * swift.file: NullableUtils
 * swift.name: NullableUtils
 * package: nullables
 */
struct Utils {

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     * nullable_arg:
     *   - num
     */
    Utils(NumberDouble* num) : numDouble(num) {}

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * nullable_arg:
     *   - first
     * nullable_return: True
     * return_value_policy: reference
     */
    static NumberDouble* max(NumberDouble* first, NumberDouble* second) {
        if (first && second) {
            if (first->value > second->value) {
                return first;
            }
            return second;
        }
        return nullptr;
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * nullable_arg:
     *   - first
     *   - second
     * nullable_return: True
     */
    static std::shared_ptr<NumberInt> max(std::shared_ptr<NumberInt> first, std::shared_ptr<NumberInt> second) {
        if (first && second) {
            if (first->value > second->value) {
                return first;
            }
            return second;
        }
        return std::shared_ptr<NumberInt>(nullptr);
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    static void checkNonnullArg(NumberDouble* number) {
        if (!number){
            throw std::invalid_argument("number cannot be nullptr.");
        }
    }

    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * return_value_policy: reference
     */
    static NumberDouble* checkNonnullReturn() {
        return nullptr;
    }

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     * nullable_return: True
     * return_value_policy: reference
     */
    NumberDouble* nullable() {
        return numDouble;
    }

    /**
     * __API__
     * action: gen_setter
     * throws: no_throw
     * nullable_arg: num
     */
    void setNullable(NumberDouble* num) {
        numDouble = num;
    }

    /**
     * __API__
     * action: gen_getter
     * throws: no_throw
     * return_value_policy: reference
     */
    NumberDouble* nonNull() {
        return numDouble;
    }

    /**
     * __API__
     * action: gen_setter
     * throws: no_throw
     */
    void setNonNull(NumberDouble* num) {
        numDouble = num;
    }

    /**
     * __API__
     * action: gen_property_setter
     * nullable_return: True
     * return_value_policy: reference
     */
    NumberDouble* numDouble;

    /**
     * __API__
     * action: gen_property_setter
     * nullable_return: False
     */
    std::shared_ptr<NumberInt> numInt;

};

/**
 * __API__
 * action: gen_function
 * package: nullables
 * swift.file: NullableUtils
 * throws: no_throw
 * nullable_arg: s
 * nullable_return: True
 */
const char* reverseString(const char* s) {
    if (s) {
        auto str = std::string(s);
        std::reverse(str.begin(), str.end());
        char* res = new char[sizeof(char) * strlen(s)];
        std::strcpy(res, str.c_str());
        return res;
    }
    return nullptr;
}

CppBind uses the nullable_arg variable to identify which arguments are nullable. It is a list of argument names. And for the nullable return value, CppBind uses the nullable_return boolean variable. In the above example, we have an overloaded method max. The first one has one nullable and one non-null argument, which returns a nullable value. The second one has two nullable arguments and returns a nullable value. In this example, you can also find a constructor taking a nullable argument and nullable getters/setters.

Note

In case of nullable pair of getter/setter methods both must be annotated similarly as gen_getter and gen_setter. If the getter is nullable_return: True, then setter should be marked as nullable_arg: <arg_name>. In the above example, we have a pair of nullable getter/setter: nullable and setNullable.

Note

Kotlin and Swift support nullable arguments. For Python, nullable arguments and return values are marked as Optional. Since all arguments are nullable in Python, CppBind does additional runtime checks not to allow passing null values where a non-null value is expected.

Now let's see some usage examples for generated bindings:

val n1 = NumberInt(1)
val n2 = NumberInt(2)

var res1 = Utils.max(n1, n2)
assert(res1?.value == n2.value)

res1 = Utils.max(null, null)
assert(res1 == null)

val d1 = NumberDouble(1.0)
val d2 = NumberDouble(2.0)

var res2 = Utils.max(d1, d2)
assert(res2?.value == d2.value)

res2 = Utils.max(null, d2)
assert(res2 == null)

// nullable getter/setter
val utils = Utils(d1)
assert(utils.nullable?.value == d1.value)
utils.nullable = null

// nullable property getter/setter
assert(utils.numDouble == null)
utils.numDouble = d2
assert(utils.numDouble?.value == d2.value)

// checking char *
assert(reverseString("abc") == "cba")
assert(reverseString(null) == null)

As you can see here ValueError is thrown when None is passed but expected value is not Optional. The same is for return values.

n1 = NumberInt(1)
n2 = NumberInt(2)

res1 = Utils.max(n1, n2)
assert res1.value == n2.value

res1 = Utils.max(None, None)
assert res1 is None

d1 = NumberDouble(1.0)
d2 = NumberDouble(2.0)

res2 = Utils.max(d1, d2)
assert res2.value == d2.value

res2 = Utils.max(None, d2)
assert res2 is None

# negative examples
try:
    Utils.check_nonnull_arg(None)
except ValueError as e:
    assert str(e) == "Utils.check_nonnull_arg's number argument cannot be None."

try:
    Utils.check_nonnull_return()
except ValueError as e:
    assert str(e) == "Utils.check_nonnull_return's return value cannot be None."

# nullable getter/setter
utils = Utils(d1)
assert utils.nullable.value == d1.value
utils.nullable = None


# negative examples
try:
    assert utils.non_null
except ValueError as e:
    assert str(e) == "Utils.non_null's return value cannot be None."

try:
    utils.non_null = None
except ValueError as e:
    assert str(e) == "Utils.non_null's value argument cannot be None."


# nullable property getter/setter
assert utils.num_double is None
utils.num_double = d2
assert utils.num_double.value == d2.value


# negative examples
try:
    utils.num_int = None
except ValueError as e:
    assert str(e) == "Utils.num_int's value argument cannot be None."

# checking char *
assert reverse_string("abc") == "cba"
assert reverse_string(None) is None

let n1 = NumInt(val: 1)
let n2 = NumInt(val: 2)

let res1 = NullableUtils.max(first: n1, second: n2)
assert(res1!.value == n2.value)

let d1 = NumDouble(val: 1.0)
let d2 = NumDouble(val: 2.0)

var res2 = NullableUtils.max(first: d1, second: d2)
assert(res2!.value == d2.value)

res2 = NullableUtils.max(first: nil, second: d2)
assert(res2 == nil)

// incorrect example for swift
// res1 = NullableUtils.max(first: nil, second: nil)
// assert(res1 == nil)

// negative examples
// NullableUtils.checkNonnullArg(number: nil)

// nullable getter/setter
let utils = NullableUtils(num: d1)
assert(utils.nullable!.value == d1.value)
utils.nullable = nil


// nullable property getter/setter
assert(utils.numDouble == nil)
utils.numDouble = d2
assert(utils.numDouble!.value == d2.value)

// negative examples
// utils.numInt = nil

// checking char *
assert(reverseString(s: "abc") == "cba")
assert(reverseString(s: nil) == nil)
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/18/2022-11:02.
 * Please do not change it manually.
 */

package com.examples.nullables

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

open class NumberInt
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(val_: Int): Long {
            val id = jConstructor(val_)
            return id
        }

        @JvmStatic
        private external fun jConstructor(val_: Int, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::nullable::NumberInt"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(val_: Int): this(CppBindObject(constructHelper(val_), true)) {
    }

    val value: Int
        get() {
            val result = jValue(cppbindObjId)

            return result
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as NumberInt
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    override fun close() {
        if (cppbindObj.owner && cppbindObj.id != 0L) {
            jFinalize(cppbindObj.id)
            cppbindObj.id = 0L
        }
    }

    /**
     * Finalize and deletes the object
     */
    protected fun finalize() {
        close()
    }

    ///// External wrapper functions ////////////
    private external fun jValue(id: Long): Int
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

open class NumberDouble
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(val_: Double): Long {
            val id = jConstructor(val_)
            return id
        }

        @JvmStatic
        private external fun jConstructor(val_: Double, vararg extraObjs: Any?): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::nullable::NumberDouble"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(val_: Double): this(CppBindObject(constructHelper(val_), true)) {
    }

    val value: Double
        get() {
            val result = jValue(cppbindObjId)

            return result
        }

    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as NumberDouble
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    override fun close() {
        if (cppbindObj.owner && cppbindObj.id != 0L) {
            jFinalize(cppbindObj.id)
            cppbindObj.id = 0L
        }
    }

    /**
     * Finalize and deletes the object
     */
    protected fun finalize() {
        close()
    }

    ///// External wrapper functions ////////////
    private external fun jValue(id: Long): Double
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

/**
 * An example with nullable arguments.
 */
open class Utils
internal constructor(obj: CppBindObject) : AutoCloseable {
    companion object {
        init {
            System.loadLibrary("wrapper_jni")
        }

        protected fun constructHelper(num: NumberDouble?): Long {
            val kotlintojdknum = num?.cppbindObjId ?: 0L
            val id = jConstructor(kotlintojdknum, num)
            return id
        }

        @JvmStatic
        private external fun jConstructor(num: Long, vararg extraObjs: Any?): Long

        fun max(first: NumberDouble?, second: NumberDouble): NumberDouble? {
            val kotlintojdkfirst = first?.cppbindObjId ?: 0L
            val kotlintojdksecond = second.cppbindObjId
            val result = jMax(kotlintojdkfirst, kotlintojdksecond, first, second)
            val jdktokotlinresult = if (result == 0L) null else NumberDouble(CppBindObject(result))
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jMax(first: Long, second: Long, vararg extraObjs: Any?): Long

        fun max(first: NumberInt?, second: NumberInt?): NumberInt? {
            val kotlintojdkfirst = first?.cppbindObjId ?: 0L
            val kotlintojdksecond = second?.cppbindObjId ?: 0L
            val result = jMax1(kotlintojdkfirst, kotlintojdksecond, first, second)
            val jdktokotlinresult = if (result == 0L) null else NumberInt(CppBindObject(result, true))
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jMax1(first: Long, second: Long, vararg extraObjs: Any?): Long

        fun checkNonnullArg(number: NumberDouble): Unit {
            val kotlintojdknumber = number.cppbindObjId
            val result = jChecknonnullarg(kotlintojdknumber, number)

            return result
        }
        @JvmStatic
        private external fun jChecknonnullarg(number: Long, vararg extraObjs: Any?): Unit

        fun checkNonnullReturn(): NumberDouble {
            val result = jChecknonnullreturn()
            val jdktokotlinresult = NumberDouble(CppBindObject(result))
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jChecknonnullreturn(): Long
        /**
         * An internal property to keep an information about the underlying C++ object type.
         * It is intended to be used by the generated code.
         */
        const val cppbindCxxTypeName: String = "cppbind::example::nullable::Utils"
    }

    protected var cppbindObj = obj
    private var refs: MutableList<Any> = mutableListOf()

    /**
     * An internal method to bind the lifetimes of the current and another object.
     * It is intended to be used by the generated code.
     */
    fun keepCppBindReference(ref: Any) {
        refs.add(ref)
    }
    /**
     * An internal getter to get the id of an object.
     * It is intended to be used by the generated code.
     */
    open val cppbindObjId: Long
        get() {
            if (cppbindObj.id == 0L) {
                throw RuntimeException("Object is not allocated")
            }
            return cppbindObj.id
        }

    /**
     * An internal property returning underlying C++ object id.
     * It is intended to be used by the generated code.
     */
    internal val cxxId: Long by lazy {
        jGetcxxid(cppbindObj.id)
    }

    /**
     * An internal property returning underlying C++ type name.
     * It is intended to be used by the generated code.
     */
    internal val cxxTypeName: String by lazy {
        jGettypebyid(cppbindObj.id)
    }

    constructor(num: NumberDouble?): this(CppBindObject(constructHelper(num), true)) {
    }

    var nullable: NumberDouble?
        get() {
            val result = jNullable(cppbindObjId)
            val jdktokotlinresult = if (result == 0L) null else NumberDouble(CppBindObject(result))
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = value?.cppbindObjId ?: 0L
            jSetnullable(cppbindObjId, kotlintojdkvalue, value)
        }

    var nonNull: NumberDouble
        get() {
            val result = jNonnull(cppbindObjId)
            val jdktokotlinresult = NumberDouble(CppBindObject(result))
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = value.cppbindObjId
            jSetnonnull(cppbindObjId, kotlintojdkvalue, value)
        }

    var numDouble: NumberDouble?
        get() {
            val result = jNumdouble(cppbindObjId)
            val jdktokotlinresult = if (result == 0L) null else NumberDouble(CppBindObject(result))
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = value?.cppbindObjId ?: 0L
            jSetnumdouble(cppbindObjId, kotlintojdkvalue, value)
        }


    var numInt: NumberInt
        get() {
            val result = jNumint(cppbindObjId)
            val jdktokotlinresult = NumberInt(CppBindObject(result, true))
            return jdktokotlinresult
        }
        set(value) {
            val kotlintojdkvalue = value.cppbindObjId
            jSetnumint(cppbindObjId, kotlintojdkvalue, value)
        }


    /**
     * CppBind generated hashCode method returning the hash of underlying C++ object id.
     */
    override fun hashCode(): Int {
        return cxxId.hashCode()
    }

    /**
     * CppBind generated equals method comparing the underlying C++ object ids.
     */
    override fun equals(other: Any?): Boolean {
        other as Utils
        return cxxId == other.cxxId
    }

    /**
     * CppBind generated toString method returning underlying C++ object type and id.
     */
    override fun toString(): String {
        return "<0x$cxxId: $cxxTypeName>"
    }

    override fun close() {
        if (cppbindObj.owner && cppbindObj.id != 0L) {
            jFinalize(cppbindObj.id)
            cppbindObj.id = 0L
        }
    }

    /**
     * Finalize and deletes the object
     */
    protected fun finalize() {
        close()
    }

    ///// External wrapper functions ////////////
    private external fun jNullable(id: Long): Long
    private external fun jSetnullable(id: Long, value: Long, valueObj: Any?): Unit
    private external fun jNonnull(id: Long): Long
    private external fun jSetnonnull(id: Long, value: Long, valueObj: Any?): Unit
    private external fun jNumdouble(id: Long): Long
    private external fun jSetnumdouble(id: Long, value: Long, valueObj: Any?): Unit
    private external fun jNumint(id: Long): Long
    private external fun jSetnumint(id: Long, value: Long, valueObj: Any?): Unit
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

fun reverseString(s: String?): String? {
    val result = jReversestring(s)
    val jdktokotlinresult = result
    return jdktokotlinresult
}

private external fun jReversestring(s: String?, vararg extraObjs: Any?): String?

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 08/11/2022-07:34.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.nullables.nullable_utils as pybind_nullable_utils_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


class NumberInt(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, val_: int):

        pass

    @property
    @bind
    def value(self) -> int:

        pass


    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class NumberDouble(metaclass=CppBindMetaclass):

    @bind
    def __init__(self, val_: float):

        pass

    @property
    @bind
    def value(self) -> float:

        pass


    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


class Utils(metaclass=CppBindMetaclass):
    """
    An example with nullable arguments.
    """

    @bind
    def __init__(self, num: Optional[NumberDouble]):

        pass

    @property
    @bind
    def nullable(self) -> Optional[NumberDouble]:

        pass

    @nullable.setter
    @bind
    def nullable(self, value: Optional[NumberDouble]):

        pass

    @property
    @bind
    def non_null(self) -> NumberDouble:

        pass

    @non_null.setter
    @bind
    def non_null(self, value: NumberDouble):

        pass

    @property
    @bind
    def num_double(self) -> Optional[NumberDouble]:

        pass

    @num_double.setter
    @bind
    def num_double(self, value: Optional[NumberDouble]):

        pass

    @property
    @bind
    def num_int(self) -> NumberInt:

        pass

    @num_int.setter
    @bind
    def num_int(self, value: NumberInt):

        pass

    @classmethod
    @bind
    def max(cls, first: Optional[NumberDouble], second: NumberDouble) -> Optional[NumberDouble]:

        pass

    @classmethod
    @bind
    def max(cls, first: Optional[NumberInt], second: Optional[NumberInt]) -> Optional[NumberInt]:

        pass

    @classmethod
    @bind
    def check_nonnull_arg(cls, number: NumberDouble) -> None:

        pass

    @classmethod
    @bind
    def check_nonnull_return(cls) -> NumberDouble:

        pass

    @bind
    def __repr__(self) -> str:
        """
        CppBind generated __repr__ method returning underlying C++ object type and id.
        """
        pass


@bind
def reverse_string(s: Optional[str]) -> Optional[str]:

    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:58.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public class NumInt {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  public let owner: Bool
  private var refs: [Any]

  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    self.cself = _cself
    self.owner = _owner
    self.refs = []
  }

  deinit {
    release_CppbindExampleNullable_NumInt(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(val: Int) {
    let swifttoscval = CInt(val)
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExampleNullable_NumInt(swifttoscval, &cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  public var value: Int {
    let result = _prop_get_CppbindExampleNullable_NumInt_value(cself)
    let sctoswiftresult = Int(result)
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::nullable::NumberInt" }
}

public class NumDouble {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  public let owner: Bool
  private var refs: [Any]

  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    self.cself = _cself
    self.owner = _owner
    self.refs = []
  }

  deinit {
    release_CppbindExampleNullable_NumDouble(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(val: Double) {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExampleNullable_NumDouble(val, &cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  public var value: Double {
    let result = _prop_get_CppbindExampleNullable_NumDouble_value(cself)
    return result
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::nullable::NumberDouble" }
}

/// An example with nullable arguments.
public class NullableUtils {

  /// An internal property to keep a reference to the original C++ object.
  /// It is intended to be used by the generated code.
  public let cself: CppBindCObject

  /// An internal property to keep track whether Swift is responsible for deallocating the underlying C++ object or not.
  /// It is intended to be used by the generated code.
  public let owner: Bool
  private var refs: [Any]

  /// internal main initializer
  internal required init(_ _cself: CppBindCObject, _ _owner: Bool = false) {
    self.cself = _cself
    self.owner = _owner
    self.refs = []
  }

  deinit {
    release_CppbindExampleNullable_NullableUtils(cself, owner)
  }

  /// An internal method to bind the lifetimes of the current and another object.
  /// It is intended to be used by the generated code.
  public func keepCppBindReference(_ object: Any) {
    self.refs.append(object)
  }

  public convenience init(num: NumDouble?) {
    let swifttoscnum = num?.cself ?? CppBindCObject(type: nil, ptr: nil)
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExampleNullable_NullableUtils(swifttoscnum, &cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  public var nullable: NumDouble? {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExampleNullable_NullableUtils_nullable(cself, &cppbindErr)
      if cppbindErr.type != nil {
        let errorType = String(cString: cppbindErr.type!)
        switch errorType {
        case ("std::exception"):
          let excObj = StdException(cppbindErr, true)
          ExceptionHandler.handleUncaughtException(excObj.what())
        default:
          cppbindErr.type.deallocate()
          ExceptionHandler.handleUncaughtException("Uncaught Exception")
        }
      }
      var sctoswiftresult: NumDouble? = nil
      if (result.ptr != nil) {
        sctoswiftresult = NumDouble(result)
      }
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = value?.cself ?? CppBindCObject(type: nil, ptr: nil)
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExampleNullable_NullableUtils_nullable(cself, swifttoscvalue, &cppbindErr)
      if cppbindErr.type != nil {
        let errorType = String(cString: cppbindErr.type!)
        switch errorType {
        case ("std::exception"):
          let excObj = StdException(cppbindErr, true)
          ExceptionHandler.handleUncaughtException(excObj.what())
        default:
          cppbindErr.type.deallocate()
          ExceptionHandler.handleUncaughtException("Uncaught Exception")
        }
      }
    }
  }

  public var nonNull: NumDouble {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExampleNullable_NullableUtils_nonNull(cself, &cppbindErr)
      if cppbindErr.type != nil {
        let errorType = String(cString: cppbindErr.type!)
        switch errorType {
        case ("std::exception"):
          let excObj = StdException(cppbindErr, true)
          ExceptionHandler.handleUncaughtException(excObj.what())
        default:
          cppbindErr.type.deallocate()
          ExceptionHandler.handleUncaughtException("Uncaught Exception")
        }
      }
      var sctoswiftresult: NumDouble
      sctoswiftresult = NumDouble(result)
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = value.cself
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExampleNullable_NullableUtils_nonNull(cself, swifttoscvalue, &cppbindErr)
      if cppbindErr.type != nil {
        let errorType = String(cString: cppbindErr.type!)
        switch errorType {
        case ("std::exception"):
          let excObj = StdException(cppbindErr, true)
          ExceptionHandler.handleUncaughtException(excObj.what())
        default:
          cppbindErr.type.deallocate()
          ExceptionHandler.handleUncaughtException("Uncaught Exception")
        }
      }
    }
  }

  public var numDouble: NumDouble? {
    get {
      let result = _prop_get_CppbindExampleNullable_NullableUtils_numDouble(cself)
      var sctoswiftresult: NumDouble? = nil
      if (result.ptr != nil) {
        sctoswiftresult = NumDouble(result)
      }
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = value?.cself ?? CppBindCObject(type: nil, ptr: nil)
      _prop_set_CppbindExampleNullable_NullableUtils_numDouble(cself, swifttoscvalue)
    }
  }

  public var numInt: NumInt {
    get {
      let result = _prop_get_CppbindExampleNullable_NullableUtils_numInt(cself)
      var sctoswiftresult: NumInt
      sctoswiftresult = NumInt(result, true)
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = value.cself
      _prop_set_CppbindExampleNullable_NullableUtils_numInt(cself, swifttoscvalue)
    }
  }

  public static func max(first: NumDouble?, second: NumDouble) -> NumDouble? {

    let swifttoscfirst = first?.cself ?? CppBindCObject(type: nil, ptr: nil)
    let swifttoscsecond = second.cself
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExampleNullable_NullableUtils_max(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    var sctoswiftresult: NumDouble? = nil
    if (result.ptr != nil) {
      sctoswiftresult = NumDouble(result)
    }
    return sctoswiftresult
  }

  public static func max(first: NumInt?, second: NumInt?) -> NumInt? {

    let swifttoscfirst = first?.cself ?? CppBindCObject(type: nil, ptr: nil)
    let swifttoscsecond = second?.cself ?? CppBindCObject(type: nil, ptr: nil)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExampleNullable_NullableUtils_max1(swifttoscfirst, swifttoscsecond, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    var sctoswiftresult: NumInt? = nil
    if (result.ptr != nil) {
      sctoswiftresult = NumInt(result, true)
    }
    return sctoswiftresult
  }

  public static func checkNonnullArg(number: NumDouble) -> Void {

    let swifttoscnumber = number.cself
    var cppbindErr = CppBindCObject()
    _func_CppbindExampleNullable_NullableUtils_checkNonnullArg(swifttoscnumber, &cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  public static func checkNonnullReturn() -> NumDouble {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExampleNullable_NullableUtils_checkNonnullReturn(&cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
    var sctoswiftresult: NumDouble
    sctoswiftresult = NumDouble(result)
    return sctoswiftresult
  }

  /// An internal property to keep an information about the underlying C++ object type.
  /// It is intended to be used by the generated code.
  class var cppbindCxxTypeName : String { return "cppbind::example::nullable::Utils" }
}

public func reverseString(s: String?) -> String? {
  let swifttoscs = s?.cString(using: String.Encoding.utf8)
  var cppbindErr = CppBindCObject()
  let result = _func_CppbindExampleNullable_reverseString(swifttoscs, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = result != nil ? String(cString: result!) : nil
  return sctoswiftresult
}

Default arguments

Default argument support for literals and enums are handled differently from default arguments with expressions. Let's go through these two cases.

Here are some sample functions with default arguments:

/**
 * A global function with enum default argument.
 * __API__
 * action: gen_function
 * kotlin.package: globs.primitives
 * package: globs
 * file: primitiveDefaults
 * throws: no_throw
 */
cppbind::example::Color optionalColor(cppbind::example::Color c = cppbind::example::Color::Red);

/**
 * A global function with string default argument.
 * __API__
 * action: gen_function
 * kotlin.package: globs.primitives
 * package: globs
 * file: primitiveDefaults
 * throws: no_throw
 */
std::string optionalString(std::string optionalStr = "abc");

/** A global function with primitive default value.
 * __API__
 * action: gen_function
 * kotlin.package: globs.primitives
 * package: globs
 * file: primitiveDefaults
 * throws: no_throw
 */
int optionalInt(int i = 5);

Here's a sample code using the above functions:

assert(optionalColor() == Color.Red)
assert(optionalColor(Color.Blue) == Color.Blue)
assert(optionalInt() == 5)
assert(optionalInt(1) == 1)
assert(optionalString() == "abc")
assert(optionalString("def") == "def")
assert optional_color() == Color.Red
assert optional_color(Color.Blue) == Color.Blue
assert optional_int() == 5
assert optional_int(1) == 1
assert optional_string() == 'abc'
assert optional_string('def') == 'def'
assert(optionalColor() == Color.Red)
assert(optionalColor(c: Color.Blue) == Color.Blue)
assert(optionalInt() == 5)
assert(optionalInt(i: 1) == 1)
assert(optionalString() == "abc")
assert(optionalString(optionalStr: "def") == "def")
Generated bindings
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/11/2022-09:04.
 * Please do not change it manually.
 */

package com.examples.globs.primitives

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
import com.examples.enums.Color

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

/**
 * A global function with enum default argument.
 */
fun optionalColor(c: Color = Color.Red): Color {
    val kotlintojdkc = c.value
    val result = jOptionalcolor(kotlintojdkc, c)
    val jdktokotlinresultOptional = Color.getByValue(result)
    if (jdktokotlinresultOptional == null) {
        ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of Color enum.")
    }
    val jdktokotlinresult = jdktokotlinresultOptional!!
    return jdktokotlinresult
}

/**
 * A global function with string default argument.
 */
fun optionalString(optionalStr: String = "abc"): String {
    val result = jOptionalstring(optionalStr)

    return result
}

/**
 * A global function with primitive default value.
 */
fun optionalInt(i: Int = 5): Int {
    val result = jOptionalint(i)

    return result
}

private external fun jOptionalcolor(c: Int, vararg extraObjs: Any?): Int
private external fun jOptionalstring(optionalStr: String, vararg extraObjs: Any?): String
private external fun jOptionalint(i: Int, vararg extraObjs: Any?): Int

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 11/24/2022-07:21.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.globs.primitiveDefaults as pybind_primitiveDefaults_pygen
import examples_lib.enums.color_pygen as enums_color_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *


@bind
def optional_color(c: enums_color_pygen.Color = enums_color_pygen.Color.Red) -> enums_color_pygen.Color:
    """
    A global function with enum default argument.
    """
    pass


@bind
def optional_string(optional_str: str = "abc") -> str:
    """
    A global function with string default argument.
    """
    pass


@bind
def optional_int(i: int = 5) -> int:
    """
    A global function with primitive default value.
    """
    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:58.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// A global function with enum default argument.
public func optionalColor(c: Color = Color.Red) -> Color {
  let swifttoscc = c.rawValue
  var cppbindErr = CppBindCObject()
  let result = _func__optionalColor(swifttoscc, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  guard let sctoswiftresult = Color(rawValue: result) else {
     ExceptionHandler.handleUncaughtException(
        "Internal error: unresolved reference to non existing field of Color enum.")
  }
  return sctoswiftresult
}

/// A global function with string default argument.
public func optionalString(optionalStr: String = "abc") -> String {
  let swifttoscoptionalStr = strdup(optionalStr)!
  var cppbindErr = CppBindCObject()
  let result = _func__optionalString(swifttoscoptionalStr, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global function with primitive default value.
public func optionalInt(i: Int = 5) -> Int {
  let swifttosci = CInt(i)
  var cppbindErr = CppBindCObject()
  let result = _func__optionalInt(swifttosci, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = Int(result)
  return sctoswiftresult
}

Complex cases like t=Task("MyTask") or t=24>>2 are handled differently. Let's take a look at the following example:

/**
 * __API__
 * action: gen_function
 * kotlin.package: globs.complex
 * package: globs
 * file: complexDefaults
 * throws: no_throw
 */
cppbind::example::Task singleComplexDefaultValue(cppbind::example::Task task = cppbind::example::Task("MyTask"));

/**
 * A global function with mixed default values.
 * __API__
 * action: gen_function
 * kotlin.package: globs.complex
 * package: globs
 * file: complexDefaults
 * throws: no_throw
 */
std::string multipleMixedDefaultValues(cppbind::example::Task task = cppbind::example::Task("DefaultTask"),
                                       int i = 1,
                                       cppbind::example::Root r = cppbind::example::Root("DefaultRoot"));

In the above example, we have two functions. The first one has one argument of type Task with a default value. In this case, CppBind generates two overloaded functions for Kotlin and Swift: one with no arguments and another one with one argument with no default value specified. The second function has three arguments of Task, i and Root. The second argument is an int, and its' default value is generated in all target languages. CppBind will generate appropriate overloaded options for Kotlin and Swift for the other two arguments. For Python, CppBind does not generate overloaded functions; instead, the None default value is generated. Although the actual default values for complex types are not visible in generated code, they work as expected.

Generated functions
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 11/10/2022-06:59.
 * Please do not change it manually.
 */

package com.examples.globs.complex

import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
import com.examples.simple.Root
import com.examples.simple.task.Task

private val INIT = run {
    System.loadLibrary("wrapper_jni");
}

fun singleComplexDefaultValue(): Task {
    val result = jSinglecomplexdefaultvalue1()
    val jdktokotlinresult = Task(CppBindObject(result, true))
    return jdktokotlinresult
}


fun singleComplexDefaultValue(task: Task): Task {
    val kotlintojdktask = task.cppbindObjId
    val result = jSinglecomplexdefaultvalue(kotlintojdktask, task)
    val jdktokotlinresult = Task(CppBindObject(result, true))
    return jdktokotlinresult
}

/**
 * A global function with mixed default values.
 */
fun multipleMixedDefaultValues(): String {
    val result = jMultiplemixeddefaultvalues1()

    return result
}


/**
 * A global function with mixed default values.
 */
fun multipleMixedDefaultValues(task: Task, i: Int = 1): String {
    val kotlintojdktask = task.cppbindObjId
    val result = jMultiplemixeddefaultvalues2(kotlintojdktask, i, task)

    return result
}


/**
 * A global function with mixed default values.
 */
fun multipleMixedDefaultValues(task: Task, i: Int = 1, r: Root): String {
    val kotlintojdktask = task.cppbindObjId
    val kotlintojdkr = r.cppbindObjId
    val result = jMultiplemixeddefaultvalues(kotlintojdktask, i, kotlintojdkr, task, r)

    return result
}

private external fun jSinglecomplexdefaultvalue1(): Long

private external fun jSinglecomplexdefaultvalue(task: Long, vararg extraObjs: Any?): Long
private external fun jMultiplemixeddefaultvalues1(): String

private external fun jMultiplemixeddefaultvalues2(task: Long, i: Int, vararg extraObjs: Any?): String

private external fun jMultiplemixeddefaultvalues(task: Long, i: Int, r: Long, vararg extraObjs: Any?): String

private external fun jGettypebyid(id: Long): String
"""
  ______ .______   .______   .______    __  .__   __.  _______  
 /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
|  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
|  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
|  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 

This file is generated by cppbind on 11/24/2022-07:17.
Please do not change it manually.
"""
from __future__ import annotations

from typing import *

import examples.globs.complexDefaults as pybind_complexDefaults_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *

if TYPE_CHECKING:
    import examples_lib.simple.root_pygen as simple_root_pygen
    import examples_lib.simple.task.task_pygen as simple_task_task_pygen


@bind
def single_complex_default_value(task: simple_task_task_pygen.PyTask = None) -> simple_task_task_pygen.PyTask:

    pass


@bind
def multiple_mixed_default_values(task: simple_task_task_pygen.PyTask = None, i: int = 1, r: simple_root_pygen.Root = None) -> str:
    """
    A global function with mixed default values.
    """
    pass
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:58.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

public func singleComplexDefaultValue() -> Task {
  var cppbindErr = CppBindCObject()
  let result = _func__singleComplexDefaultValue_1(&cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  var sctoswiftresult: Task
  sctoswiftresult = Task(result, true)
  return sctoswiftresult
}

public func singleComplexDefaultValue(task: Task) -> Task {
  let swifttosctask = task.cself
  var cppbindErr = CppBindCObject()
  let result = _func__singleComplexDefaultValue(swifttosctask, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  var sctoswiftresult: Task
  sctoswiftresult = Task(result, true)
  return sctoswiftresult
}

/// A global function with mixed default values.
public func multipleMixedDefaultValues() -> String {
  var cppbindErr = CppBindCObject()
  let result = _func__multipleMixedDefaultValues_1(&cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global function with mixed default values.
public func multipleMixedDefaultValues(task: Task, i: Int = 1) -> String {
  let swifttosctask = task.cself
  let swifttosci = CInt(i)
  var cppbindErr = CppBindCObject()
  let result = _func__multipleMixedDefaultValues_2(swifttosctask, swifttosci, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

/// A global function with mixed default values.
public func multipleMixedDefaultValues(task: Task, i: Int = 1, r: Root) -> String {
  let swifttosctask = task.cself
  let swifttosci = CInt(i)
  let swifttoscr = r.cself
  var cppbindErr = CppBindCObject()
  let result = _func__multipleMixedDefaultValues(swifttosctask, swifttosci, swifttoscr, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
  let sctoswiftresult = String(cString: result)
  defer {
    result.deallocate()
  }
  return sctoswiftresult
}

And here are some usage examples:

assert(multipleMixedDefaultValues() == "DefaultTask1DefaultRoot")
assert(multipleMixedDefaultValues(Task("ABC")) == "ABC1DefaultRoot")
assert(multipleMixedDefaultValues(Task("ABC"), 2) == "ABC2DefaultRoot")
assert(multipleMixedDefaultValues(Task("ABC"), r=Root("Path") ) == "ABC1Path")
assert(multipleMixedDefaultValues(Task("ABC"), 2, Root("Path") ) == "ABC2Path")
assert multiple_mixed_default_values() == "DefaultTask1DefaultRoot"
assert multiple_mixed_default_values(Task("ABC")) == "ABC1DefaultRoot"
assert multiple_mixed_default_values(Task("ABC"), i=2) == "ABC2DefaultRoot"
assert multiple_mixed_default_values(Task("ABC"), r=Root("Path")) == "ABC1Path"
assert multiple_mixed_default_values(Task("ABC"), i=2, r=Root("Path")) == "ABC2Path"
assert(multipleMixedDefaultValues() == "DefaultTask1DefaultRoot")
assert(multipleMixedDefaultValues(task: Task(title: "ABC")) == "ABC1DefaultRoot")
assert(multipleMixedDefaultValues(task: Task(title: "ABC"), i: 2) == "ABC2DefaultRoot")
assert(multipleMixedDefaultValues(task: Task(title: "ABC"), r: Root(path: "Path") ) == "ABC1Path")
assert(multipleMixedDefaultValues(task: Task(title: "ABC"), i: 2, r: Root(path: "Path") ) == "ABC2Path")

Return value policies

C++ and target languages may differently manage the memory and lifetime of objects. Having only the return value type, CppBind cannot identify whether the binding language will take care of deallocating the returned object or C++ part should handle that. CppBind provides a variable named return_value_policy to control this. Using return_value_policy variable user can override default policies.

The default policies for getters and methods are different. For getters (properties) the default policy is reference_internal. For methods, the default policy is automatic.

Supported return value policies are:

  • copy - Create an object copy and give ownership of the new object to the target language. The lifetimes of these two objects are decoupled.
  • move - Move the returned object into a new one and give ownership of the new object to the target language. The lifetimes of these two objects are decoupled.
  • take_ownership - Reference an existing object but give ownership to the target language. The target language is responsible for deallocating it.
  • reference - Reference an existing object but do not give ownership to the target language. C++ is responsible for deallocating it.
  • automatic - This policy falls back to take_ownership when the return value is a pointer and move and copy for rvalue and lvalue references.
  • automatic_reference - Falls back to move and copy for lvalue and rvalue references, respectively, but falls back to reference when the return type is a pointer.
  • reference_internal - This policy is like reference but also binds the returned object's lifetime with the lifetime of its parent object, i.e., the parent object won't be deallocated until the returned object is not deallocated.

Let's take a look at the following example:

/**
 * __API__
 * action: gen_class
 * shared_ref: False
 * package: rv_policies
 */
class Singleton {
public:
    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * return_value_policy: reference
     */
    static Singleton& getInstance();
    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     * return_value_policy: reference
     */
    static Singleton* getInstancePtr();

    Singleton(const Singleton&) = delete;
    void operator=(const Singleton&) = delete;

private:
    Singleton();
    static Singleton* _instance;
};

In this example, we have two members returning the same singleton instance by reference and pointer. The default return value policy for member functions is automatic, which falls back to take_ownership for pointers. This means ownership is given to the binding language responsible for deallocating the returned object. In the case of references, it falls back to the copy policy, which creates a copy of the returned object, and its owner is the target language. Notice that if the default policy is used, the generated code for the first one won't compile as the copy constructor is deleted. In this example, the default policies for both cases are not what we want. We have specified reference policy for both cases not to pass the ownership to the binding language and not create a new copy.

Now let's take a look at another example:

/**
 * __API__
 * action: gen_class
 * shared_ref: False
 * package: rv_policies
 */
class Factory {
public:
    /**
     * __API__
     * action: gen_method
     * throws: no_throw
     */
    static Factory* create();

private:
    Factory();
};

Here we have a factory method create. As was discussed previously the default policy is take_ownership, which is the right policy for this case as we want to give ownership over the returned object to the target language.

Note

Object caching for Kotlin and Swift is not supported yet. Each function call creates a new binding object with different ownership depending on the function's return value policy.

Note

copy and move are used, respectively, if the object is returned by value or by rvalue reference.

Note

For shared pointers, take_ownership is always used.

Keep alive policy

Besides the return value policies, CppBind supports the keep_alive policy to bind the argument's lifetime to this object's lifetime. This ensures that the object won't be deallocated by target language Garbage Collector until the object that keeps a reference on it is alive.

Let's take a look at the following example:

/**
 * __API__
 * action: gen_class
 * shared_ref: False
 * package: rv_policies
 */
class Employer {
public:
    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     * keep_alive: [1]
     */
    Employer(const std::vector<Employee*>& employees);

    /**
     * __API__
     * action: gen_constructor
     * throws: no_throw
     * keep_alive: [1]
     */
    void addEmployee(Employee* employee);


private:
    std::vector<Employee*> _employees;
};

In the above example, Employer holds references for Employee. The constructor and the method addEmployee are annotated with the keep_alive variable to keep added employees alive at least until the employer is alive. Otherwise, added employees might be deallocated before the destruction of employer, which causes employer to hold invalid data.

Note

If the argument is a container(e.g., std::vector), then the policy is applied to all its elements.

Note

The indexing of arguments starts with one, and the policy can be applied to all arguments.

Note

When applying the keep_alive policy, strong reference cycles may occur. Let's assume we have two types, and each keeps a reference to the other. Applying the keep_alive policy for both, a strong reference cycle will occur. Currently, CppBind does not detect reference cycles, so it's up to users to be careful not to create them.

Note

For shared pointers, it's redundant to specify the keep_alive policy.


Last update: December 1, 2022