Skip to content

Exception handling

CppBind supports exception handling by catching thrown exception objects in C++ and rethrowing them in a target language. The user must specify the list of possible thrown exception classes in throws variable. Let's take a look at the following example demonstrating exception handling:

Note

CppBind uses pybind library to generate Python bindings, which already has own mechanism for exception handling. Pybind translates C++ standard exceptions to their Python analogs using an exception correspondence map. Pybind translates all user-defined exceptions to Python RuntimeError. This also sets some constraints on CppBind, so currently, CppBind doesn't support Python exceptions as it's done for other target languages. The user-defined exceptions list is not relevant for Python, and is ignored. The user still must define the throws variable with a placeholder value. no_throw value works fine in this case. This requirement keeps API annotations style convenient between all target languages.

/**
 * __API__
 * action: gen_constructor
 * throws:
 *   - std::invalid_argument
 */
 ThrowExc(bool do_throw=false) {
    if (do_throw) throw std::invalid_argument("inv_arg");
 }

/**
 * __API__
 * action: gen_method
 * throws:
 *   - std::out_of_range
 *   - cppbind::example::SystemError
 */
static int getByKey(const std::map<int, int>& m, int key) {
    return m.at(key);
}

/**
 * Throws exception with return value of type string.
 * __API__
 * action: gen_method
 * throws: std::invalid_argument
 */
static std::string throwsWithReturnValueString() {
    throw std::invalid_argument("return value error");
}

/**
 * Throws exception with return value of cppbind type.
 * __API__
 * action: gen_method
 * throws: std::invalid_argument
 */
static cppbind::example::Task* throwsWithReturnValuePtr() {
    throw std::invalid_argument("return value error");
}

throws variable is mandatory for methods, constructors, and functions (also for getters and setters). If a method doesn't throw an exception, the user must set the variable to a special no_throw value. This is done as a requirement so that the user does not forget about the ability of a method to throw an exception. An example of an empty exception list looks like this:

/**
* __API__
* action: gen_method
* throws: no_throw
*/
virtual int errNum() {
    return err_num;
}

Note

The order of listed exception classes in the throws variable is important. CppBind preserves user-defined order when catching/rethrowing exceptions.

Note

Swift language doesn't support exception throwing from getter/setter, so the user should set the value of the throws variable to no_throw for getter/setter functions. CppBind will give an error otherwise.

The throws list accepts API annotated standard and user-defined exception classes. On a target language side, CppBind keeps correspondence between those classes. CppBind generates bindings for standard exceptions by providing binding predefined rules for std::exception and its descendant classes. The binding rules for standard exceptions are defined in "std_exc_api.yaml" config file, which looks like this:

CppBind API config for standard exceptions
# Copyright (c) 2022 PicsArt, Inc.
# All rights reserved. Use of this source code is governed by a
# MIT-style license that can be found in the LICENSE file.

- type: "std::exception"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdException
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"
    is_exception: True
    include_cxx:
      - <stdexcept>
      - <new>
      - <typeinfo>

- type: "std::exception::what()"
  vars:
    kotlin.action: gen_method
    swift.action: gen_method
    python.action:
    throws: no_throw

- type: "std::runtime_error"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdRuntimeError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::logic_error"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdLogicError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::bad_alloc"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdBadAlloc
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::bad_cast"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdBadCast
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::bad_typeid"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdBadTypeId
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::overflow_error"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdOverflowError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::range_error"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdRangeError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::underflow_error"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdUnderflowError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::invalid_argument"
  vars:
    kotlin.action: gen_class
    swift.action: gen_class
    python.action:
    name: StdInvalidArgument
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::length_error"
  vars:
    swift.action: gen_class
    kotlin.action: gen_class
    python.action:
    name: StdLengthError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::out_of_range"
  vars:
    swift.action: gen_class
    kotlin.action: gen_class
    python.action:
    name: StdOutOfRange
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

- type: "std::domain_error"
  vars:
    swift.action: gen_class
    kotlin.action: gen_class
    python.action:
    name: StdDomainError
    package_prefix: "{{helpers_package_prefix}}"
    package: "{{exception_helpers_package}}"
    file: "{{exception_file_name}}"

Note

Since CppBind generate try/catch blocks in C bindings for catching an exception, it uses C++ std exception classes, and therefore we need to include the header files where std exceptions are defined. Those header files are included via the include_cxx variable (see the example above). Here is the list of required includes:

#include <stdexcept>
#include <new>
#include <typeinfo>

If a user-defined exception is derived from std::exception, it is automatically throwable in a target language. If the user wants a class to be throwable in a target language and not to be derived from std::exception, the is_exception variable for that class must be set to True (default value is False).

Note

User-defined exception classes must have a copy constructor since CppBind copies the exception object before rethrowing it in a target language. CppBind needs a copy object since the original exception object is deleted when its lifetime is ended.

If CppBind catches an exception not from the user-defined list, it throws an unexpected exception and calls an uncaught exception handler callback. CppBind defines ExceptionHandler class in a utility package (one for each target language) to handle uncaught exceptions. The default handler aborts program execution immediately, but the user can set a custom callback, which will be called when an unhandled exception is detected, to change this behaviour. The mentioned package looks like following:

/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 06/23/2021-14:46.
 * Please do not change it manually.
 */

package com.examples.cppbind

import kotlin.system.exitProcess

public class ExceptionHandler {
    companion object {
        private var uncaughtExceptionHandler = {errMsg: String -> defaultHandler(errMsg)}

        fun defaultHandler(errMsg: String) {
            println("Uncaught exception is found: ${errMsg}")
            exitProcess(1)
        }

        @JvmStatic
        fun handleUncaughtException(errMsg: String) {
            uncaughtExceptionHandler(errMsg)
        }

        fun setUncaughtExceptionHandler(handler: (String) -> Unit) {
            uncaughtExceptionHandler = {errMsg: String -> handler(errMsg)}
        }

        fun unsetUncaughtExceptionHandler() {
            uncaughtExceptionHandler = {errMsg: String -> defaultHandler(errMsg)}
        }
    }
} 
/**
 *   ______ .______   .______   .______    __  .__   __.  _______
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/
 * 
 * This file is generated by cppbind on 07/21/2021-07:17.
 * Please do not change it manually.
 */

public class ExceptionHandler {

    static var uncaughtExceptionHandler = defaultHandler

    static func defaultHandler(_ err_msg: String) -> Never {
        print("Uncaught exception is found: \(err_msg)")
        fatalError("Unexpected Exception")
    }

    static func handleUncaughtException(_ err_msg : String) -> Never {
        uncaughtExceptionHandler(err_msg)
    }

    public static func setUncaughtExceptionHandler(_ handler: @escaping (String) -> Never) {
        uncaughtExceptionHandler = handler
    }

    public static func unsetUncaughtExceptionHandler() {
        uncaughtExceptionHandler = defaultHandler
    }
}

CppBind always catches std::exception before catching all (catch(...)) exceptions to have a more informative error message when the exception class is derived from std::exception.

After generating bindings for a target language, we can call methods that can throw an exception and test results with catch blocks:

try {
    ThrowExc.getByKey(mapOf(1 to 1), 0)
} catch (e: StdOutOfRange) {
    assert(e.what().contains("map::at"))
} catch (e: Exception) {
    assert(false)
}

// assert everything is ok for returned pointer value when an exception is raised
try {
  ThrowExc.throwsWithReturnValuePtr()
} catch (e: StdInvalidArgument) {
    assert(e.what() == "return value error")
} catch (e: Exception) {
  assert(false)
}

// assert everything is ok for returned string value when an exception is raised
try {
    ThrowExc.throwsWithReturnValueString()
} catch (e: StdInvalidArgument) {
    assert(e.what() == "return value error")
} catch (e: Exception) {
    assert(false)
}

// checking throwing constructor
try {
    ThrowExc(true)
    assert(false)
} catch (e: StdInvalidArgument) {
    assert(e.what() == "inv_arg")
} catch (e: Exception) {
    assert(false)
}

try {
    MiscExc.returnInteger(true)
    assert(false)
} catch (e: StdOutOfRange) {
    assert(e.what() == "error")
} catch (e: Exception) {
    assert(false)
}

try {
    MiscExc.raiseErrorByType("simple_child")
} catch (e: SimpleChildException) {
    assert(e.errNum() == 100)
} catch (e: Exception) {
    assert(false)
}
let result = try? ThrowExc.getByKey(m: [1 : 1], key: 0)
assert(result == nil)

do {
    let _ = try ThrowExc.getByKey(m: [1 : 1], key: 0)
} catch is StdOutOfRange {
} catch {
    assert(false)
}

// assert everything is ok for returned pointer value when an exception is raised
do {
  let _ = try ThrowExc.throwsWithReturnValuePtr()
} catch let err as StdInvalidArgument {
  assert(err.what() == "return value error")
} catch {
  assert(false)
}

// assert everything is ok for returned string value when an exception is raised
do {
    let _ = try ThrowExc.throwsWithReturnValueString()
} catch let err as StdInvalidArgument {
    assert(err.what() == "return value error")
} catch {
    assert(false)
}

// checking throwing constructor
do {
    let _ = try ThrowExc(doThrow: true)
} catch let err as StdInvalidArgument {
    assert(err.what() == "inv_arg")
} catch {
    assert(false)
}

do {
    let _ = try MiscExc.returnInteger(doThrow: true)
    assert(false)
} catch is StdOutOfRange {
} catch {
    assert(false)
}

do {
    try MiscExc.raiseErrorByType(errType: "simple_child")
} catch let err as SimpleChildException {
    assert(err.errNum() == 100)
} catch {
    assert(false)
}

Note

In the last usage example, you can notice that we called the custom exception class SimpleChildException method errNum when an exception was caught. As the custom exception class and its methods have API annotations, we have corresponding bindings generated, and thus we can use class methods.

Binding codes when "throws" exception list is not empty
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 11/10/2022-06:59.
 * Please do not change it manually.
 */

package com.examples.exceptions

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

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

/**
 * An example of a global function throwing an exception.
 */
fun throwExc(do_throw: Boolean = false): Unit {
    val result = jThrowexc(do_throw)

    return result
}

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

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

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

        fun getByKey(m: Map<Int, Int>, key: Int): Int {

            val tmpKeyKotlintojdkm = IntArray(m.size) 
            val tmpValKotlintojdkm = IntArray(m.size) 
            val kotlintojdkm = Pair<IntArray, IntArray>(tmpKeyKotlintojdkm, tmpValKotlintojdkm)
            var indexM = 0
            for ((keyM, valueM) in m) {


                tmpKeyKotlintojdkm[indexM] = keyM
                tmpValKotlintojdkm[indexM] = valueM
                ++indexM
            }
            val result = jGetbykey(kotlintojdkm, key, m)

            return result
        }
        @JvmStatic
        private external fun jGetbykey(m: Pair<IntArray, IntArray>, key: Int, vararg extraObjs: Any?): Int

        /**
         * Throws exception with return value of type string.
         */
        fun throwsWithReturnValueString(): String {
            val result = jThrowswithreturnvaluestring()

            return result
        }
        @JvmStatic
        private external fun jThrowswithreturnvaluestring(): String

        /**
         * Throws exception with return value of cppbind type.
         */
        fun throwsWithReturnValuePtr(): Task {
            val result = jThrowswithreturnvalueptr()
            val jdktokotlinresult = Task(CppBindObject(result, true))
            return jdktokotlinresult
        }
        @JvmStatic
        private external fun jThrowswithreturnvalueptr(): 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::exceptions::ThrowExc"
    }

    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(do_throw: Boolean = false): this(CppBindObject(constructHelper(do_throw), true)) {
    }

    var prop: String
        get() {
            val result = jProp(cppbindObjId)

            return result
        }
        set(value) {

            jSetprop(cppbindObjId, value, value)
        }

    /**
     * An example of a getter/setter pair with the different 'throws' lists (for checking Kotlin getter/setter exception handling).
     */
    var prop2: String
        get() {
            val result = jProp2(cppbindObjId)

            return result
        }
        set(value) {

            jSetprop2(cppbindObjId, value, 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 ThrowExc
        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 jProp(id: Long): String
    private external fun jSetprop(id: Long, value: String, valueObj: Any?): Unit
    private external fun jProp2(id: Long): String
    private external fun jSetprop2(id: Long, value: String, valueObj: Any?): Unit
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jThrowexc(do_throw: Boolean, vararg extraObjs: Any?): Unit

private external fun jGettypebyid(id: Long): String
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/14/2022-10:58.
 * Please do not change it manually.
 */

import CWrapper
import Foundation

/// An example of a global function throwing an exception.
public func throwExc(doThrow: Bool = false) throws -> Void {
  var cppbindErr = CppBindCObject()
  _func_CppbindExceptions_throwExc(doThrow, &cppbindErr)
  if cppbindErr.type != nil {
    let errorType = String(cString: cppbindErr.type!)
    switch errorType {
    case ("std::invalid_argument"):
      throw StdInvalidArgument(cppbindErr, true)
    case ("std::exception"):
      let excObj = StdException(cppbindErr, true)
      ExceptionHandler.handleUncaughtException(excObj.what())
    default:
      cppbindErr.type.deallocate()
      ExceptionHandler.handleUncaughtException("Uncaught Exception")
    }
  }
}

public class ThrowExc {

  /// 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_CppbindExceptions_ThrowExc(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(doThrow: Bool = false) throws {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExceptions_ThrowExc(doThrow, &cppbindErr), true)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::invalid_argument"):
        throw StdInvalidArgument(cppbindErr, true)
      case ("std::exception"):
        let excObj = StdException(cppbindErr, true)
        ExceptionHandler.handleUncaughtException(excObj.what())
      default:
        cppbindErr.type.deallocate()
        ExceptionHandler.handleUncaughtException("Uncaught Exception")
      }
    }
  }

  /// An example to check swift throwing property getter
  public var prop1: String {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExceptions_ThrowExc_prop1(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")
        }
      }
      let sctoswiftresult = String(cString: result)
      defer {
        result.deallocate()
      }
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = strdup(value)!
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExceptions_ThrowExc_prop1(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 static func getByKey(m: Dictionary<Int, Int>, key: Int) throws -> Int {

    let _swifttoscmKey = UnsafeMutablePointer<CInt>.allocate(
      capacity: m.count)
    let _swifttoscmVal = UnsafeMutablePointer<CInt>.allocate(
      capacity: m.count)
    var swifttoscm = CppBindCDataMap()
    swifttoscm.keys = UnsafeMutableRawPointer(_swifttoscmKey)
    swifttoscm.values = UnsafeMutableRawPointer(_swifttoscmVal)
    swifttoscm.size = Int64(m.count)
    var mIdx = 0
    for (mKey, mVal) in m {
      let swifttoscmKey = CInt(mKey)
      let swifttoscmVal = CInt(mVal)
      _swifttoscmKey[mIdx] = swifttoscmKey
      _swifttoscmVal[mIdx] = swifttoscmVal
      mIdx += 1
    }
    let swifttosckey = CInt(key)
    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExceptions_ThrowExc_getByKey(swifttoscm, swifttosckey, &cppbindErr)

    swifttoscm.keys.deallocate()
    swifttoscm.values.deallocate()
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::out_of_range"):
        throw StdOutOfRange(cppbindErr, true)
      case ("cppbind::example::SystemError"):
        throw SystemError(cppbindErr, true)
      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
  }

  /// Throws exception with return value of type string.
  public static func throwsWithReturnValueString() throws -> String {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExceptions_ThrowExc_throwsWithReturnValueString(&cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::invalid_argument"):
        throw StdInvalidArgument(cppbindErr, true)
      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
  }

  /// Throws exception with return value of cppbind type.
  public static func throwsWithReturnValuePtr() throws -> Task {

    var cppbindErr = CppBindCObject()
    let result = _func_CppbindExceptions_ThrowExc_throwsWithReturnValuePtr(&cppbindErr)
    if cppbindErr.type != nil {
      let errorType = String(cString: cppbindErr.type!)
      switch errorType {
      case ("std::invalid_argument"):
        throw StdInvalidArgument(cppbindErr, true)
      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
  }

  /// 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::exceptions::ThrowExc" }
}
Binding codes when exception list is empty (throws=True)
/**
 *   ______ .______   .______   .______    __  .__   __.  _______  
 *  /      ||   _  \  |   _  \  |   _  \  |  | |  \ |  | |       \ 
 * |  ,----'|  |_)  | |  |_)  | |  |_)  | |  | |   \|  | |  .--.  |
 * |  |     |   ___/  |   ___/  |   _  <  |  | |  . `  | |  |  |  |
 * |  `----.|  |      |  |      |  |_)  | |  | |  |\   | |  '--'  |
 *  \______|| _|      | _|      |______/  |__| |__| \__| |_______/ 
 * 
 * This file is generated by cppbind on 08/18/2022-11:02.
 * Please do not change it manually.
 */

package com.examples.exceptions

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

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

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

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

        fun noop(): Unit {
            val result = jNoop()

            return result
        }
        @JvmStatic
        private external fun jNoop(): Unit
        /**
         * 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::exceptions::NoThrowExc"
    }

    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(do_throw: Boolean = false): this(CppBindObject(constructHelper(do_throw), true)) {
    }

    var prop: String
        get() {
            val result = jProp(cppbindObjId)

            return result
        }
        set(value) {

            jSetprop(cppbindObjId, value, 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 NoThrowExc
        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 jProp(id: Long): String
    private external fun jSetprop(id: Long, value: String, valueObj: Any?): Unit
    private external fun jFinalize(id: Long): Unit
    private external fun jGetcxxid(id: Long): Long
}

private external fun jGettypebyid(id: Long): String

Note

For Kotlin we rethrow caught exception from C binding via JNI special functions. It means that exception handling section of code is written in C binding file. Here is an example of C binding file.

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

import CWrapper
import Foundation

public class NoThrowExc {

  /// 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_CppbindExceptions_NoThrowExc(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(doThrow: Bool = false) {
    var cppbindErr = CppBindCObject()
    self.init(create_CppbindExceptions_NoThrowExc(doThrow, &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 prop: String {
    get {
      var cppbindErr = CppBindCObject()
      let result = _prop_get_CppbindExceptions_NoThrowExc_prop(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")
        }
      }
      let sctoswiftresult = String(cString: result)
      defer {
        result.deallocate()
      }
      return sctoswiftresult
    }

    set(value) {
      let swifttoscvalue = strdup(value)!
      var cppbindErr = CppBindCObject()
      _prop_set_CppbindExceptions_NoThrowExc_prop(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 static func noop() -> Void {

    var cppbindErr = CppBindCObject()
    _func_CppbindExceptions_NoThrowExc_noop(&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")
      }
    }
  }

  /// 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::exceptions::NoThrowExc" }
}

Last update: December 1, 2022