Enums¶
Now let's generate a binding for an enum. Here is the Color
enum
definition:
/**
* Color Enum.
* __API__
* action: gen_enum
* package: enums
* python.code_fragment: |
* def __str__(self):
* return str(self.value)
* kotlin.code_fragment: |
* override fun toString(): String {
* return this.value.toString()
* }
* swift.bases_list: CustomStringConvertible
* swift.code_fragment: |
* public var description: String {
* return "\(self.rawValue)"
* }
*/
enum class Color {
/**
* Red = 1
*/
Red = 1,
/**
* Green = 2
*/
Green = 2,
/**
* Blue = 20
*/
Blue = 20
};
/**
* __API__
* action: gen_enum
* package: enums
* enum_case_name_prefix: Shade
* enum_excluded_cases:
* - InternalField
*/
enum class ColorShade {
/// Light = 1
Light = 1,
/// Dark = 2
///
Dark = 2,
///
/// SemiLight = 3
///
SemiLight = 3,
/**
* SemiDark = 4
*/
SemiDark = 4,
/// Unused field
InternalField = 5
};
As shown in the above example, we can extend enums logic by using the
code_fragment variable. Code fragments defined with this variable
are appended to the enum definition. In this example, we added the
custom conversion from enum to string for all three languages. Notice
that for Swift, we have also used the bases_list variable to make
the enum implement the CustomStringConvertible
protocol. We can also
customize enum case field names using the enum_case_name_prefix
variable, which can be used to add a user-defined prefix string to enum
field names in the target language.
In cases some of the original enum fields are for internal usage, and the user doesn't want to expose them in target language bindings, the enum_excluded_cases variable can be used to specify the list of excluded fields. If those fields are used as a default value for a function/constructor argument, CppBind skips that default value generation in target language bindings. If the user has a function that returns an excluded enum field, CppBind terminates the main program during the function call and provides the user with an appropriate error message.
And the Frame struct using it:
/**
* Class Frame.
* __API__
* action: gen_class
* package: enums
*/
struct Frame {
/**
* __API__
* action: gen_constructor
* throws: no_throw
*/
Frame() {};
/**
* __API__
* action: gen_property_setter
*/
Color backgroundColor;
/**
* __API__
* action: gen_property_setter
*/
ColorShade backgroundColorShade;
/**
* __API__
* action: gen_method
* throws: no_throw
*/
Color getNextColor(const Color& color) {
switch(color) {
case Color::Red: return Color::Green;
case Color::Green: return Color::Blue;
case Color::Blue: return Color::Red;
}
return Color::Red;
}
};
Note
We are generating property_setter for public field
backgroundColor
. A writable property field corresponds to it in the
target language. To generate a read-only field, we should use
property_getter instead.
Usage examples:
assert(Color.Red.value == 1)
assert(Color.Blue.value == 20)
assert(Color.Blue.toString() == "20")
val frame = Frame()
frame.backgroundColor = Color.Red
assert(frame.backgroundColor == Color.Red)
assert Color.Red.value == 1
assert Color.Blue.value == 20
assert Color.Green.value == 2
assert int(Color.Blue) == 20
assert str(Color.Blue) == '20'
red = Color(1)
assert red == Color.Red
assert isinstance(Color.Red, Color)
frame = Frame()
frame.background_color = Color.Red
assert frame.background_color == Color.Red
assert(Color.Red.rawValue == 1)
assert(Color.Blue.rawValue == 20)
assert(String(describing: Color.Blue) == "20")
let frame = Frame()
frame.backgroundColor = Color.Red
assert(frame.backgroundColor == Color.Red)
Generated codes for Color and Frame
Here is the generated Kotlin code for Color:
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 08/11/2022-09:04.
* Please do not change it manually.
*/
package com.examples.enums
import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
/**
* Color Enum.
*/
enum class Color(val value: Int) {
/**
* Red = 1
*/
Red(1),
/**
* Green = 2
*/
Green(2),
/**
* Blue = 20
*/
Blue(20);
companion object {
private val values = values()
fun getByValue(value: Int) = values.firstOrNull { it.value == value }
}
override fun toString(): String {
return this.value.toString()
}
}
enum class ColorShade(val value: Int) {
/**
* Light = 1
*/
ShadeLight(1),
/**
* Dark = 2
*/
ShadeDark(2),
/**
* SemiLight = 3
*/
ShadeSemiLight(3),
/**
* SemiDark = 4
*/
ShadeSemiDark(4);
companion object {
private val values = values()
fun getByValue(value: Int) = values.firstOrNull { it.value == value }
}
}
private external fun jGettypebyid(id: Long): String
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 08/18/2022-11:02.
* Please do not change it manually.
*/
package com.examples.enums
import com.examples.cppbind.*
import com.examples.cppbind.exceptions.*
/**
* Class Frame.
*/
open class Frame
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
/**
* 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::Frame"
}
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)) {
}
var backgroundColor: Color
get() {
val result = jBackgroundcolor(cppbindObjId)
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
}
set(value) {
val kotlintojdkvalue = value.value
jSetbackgroundcolor(cppbindObjId, kotlintojdkvalue, value)
}
var backgroundColorShade: ColorShade
get() {
val result = jBackgroundcolorshade(cppbindObjId)
val jdktokotlinresultOptional = ColorShade.getByValue(result)
if (jdktokotlinresultOptional == null) {
ExceptionHandler.handleUncaughtException("Internal error: unresolved reference to non existing field of ColorShade enum.")
}
val jdktokotlinresult = jdktokotlinresultOptional!!
return jdktokotlinresult
}
set(value) {
val kotlintojdkvalue = value.value
jSetbackgroundcolorshade(cppbindObjId, kotlintojdkvalue, value)
}
fun getNextColor(color: Color): Color {
val kotlintojdkcolor = color.value
val result = jGetnextcolor(cppbindObjId, kotlintojdkcolor, color)
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
}
/**
* 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 Frame
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 jBackgroundcolor(id: Long): Int
private external fun jSetbackgroundcolor(id: Long, value: Int, valueObj: Any?): Unit
private external fun jBackgroundcolorshade(id: Long): Int
private external fun jSetbackgroundcolorshade(id: Long, value: Int, valueObj: Any?): Unit
private external fun jGetnextcolor(id: Long, color: Int, vararg extraObjs: Any?): Int
private external fun jFinalize(id: Long): Unit
private external fun jGetcxxid(id: Long): Long
}
private external fun jGettypebyid(id: Long): String
Here is the generated Python code for Color:
"""
______ .______ .______ .______ __ .__ __. _______
/ || _ \ | _ \ | _ \ | | | \ | | | \
| ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
| | | ___/ | ___/ | _ < | | | . ` | | | | |
| `----.| | | | | |_) | | | | |\ | | '--' |
\______|| _| | _| |______/ |__| |__| \__| |_______/
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.enums.color as pybind_color_pygen
from examples_lib.cppbind.cppbind_metaclass_pygen import *
from examples_lib.cppbind.cppbind_utils_pygen import *
class Color(metaclass=CppBindEnumMetaclass):
"""
Color Enum.
"""
# Red = 1
Red = pybind_color_pygen.Color.Red
# Green = 2
Green = pybind_color_pygen.Color.Green
# Blue = 20
Blue = pybind_color_pygen.Color.Blue
def __int__(self):
return self.value
def __str__(self):
return str(self.value)
class ColorShade(metaclass=CppBindEnumMetaclass):
# Light = 1
ShadeLight = pybind_color_pygen.ColorShade.ShadeLight
# Dark = 2
ShadeDark = pybind_color_pygen.ColorShade.ShadeDark
# SemiLight = 3
ShadeSemiLight = pybind_color_pygen.ColorShade.ShadeSemiLight
# SemiDark = 4
ShadeSemiDark = pybind_color_pygen.ColorShade.ShadeSemiDark
def __int__(self):
return self.value
"""
______ .______ .______ .______ __ .__ __. _______
/ || _ \ | _ \ | _ \ | | | \ | | | \
| ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
| | | ___/ | ___/ | _ < | | | . ` | | | | |
| `----.| | | | | |_) | | | | |\ | | '--' |
\______|| _| | _| |______/ |__| |__| \__| |_______/
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.enums.frame as pybind_frame_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 color_pygen
class Frame(metaclass=CppBindMetaclass):
"""
Class Frame.
"""
@bind
def __init__(self):
pass
@property
@bind
def background_color(self) -> color_pygen.Color:
pass
@background_color.setter
@bind
def background_color(self, value: color_pygen.Color):
pass
@property
@bind
def background_color_shade(self) -> color_pygen.ColorShade:
pass
@background_color_shade.setter
@bind
def background_color_shade(self, value: color_pygen.ColorShade):
pass
@bind
def get_next_color(self, color: color_pygen.Color) -> color_pygen.Color:
pass
@bind
def __repr__(self) -> str:
"""
CppBind generated __repr__ method returning underlying C++ object type and id.
"""
pass
Here is the generated Swift code for Color:
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 08/14/2022-10:58.
* Please do not change it manually.
*/
import CWrapper
import Foundation
/// Color Enum.
public enum Color: CInt, CustomStringConvertible {
/// Red = 1
case Red = 1
/// Green = 2
case Green = 2
/// Blue = 20
case Blue = 20
public var description: String {
return "\(self.rawValue)"
}
}
public enum ColorShade: CInt {
/// Light = 1
case ShadeLight = 1
/// Dark = 2
case ShadeDark = 2
/// SemiLight = 3
case ShadeSemiLight = 3
/// SemiDark = 4
case ShadeSemiDark = 4
}
/**
* ______ .______ .______ .______ __ .__ __. _______
* / || _ \ | _ \ | _ \ | | | \ | | | \
* | ,----'| |_) | | |_) | | |_) | | | | \| | | .--. |
* | | | ___/ | ___/ | _ < | | | . ` | | | | |
* | `----.| | | | | |_) | | | | |\ | | '--' |
* \______|| _| | _| |______/ |__| |__| \__| |_______/
*
* This file is generated by cppbind on 08/14/2022-10:58.
* Please do not change it manually.
*/
import CWrapper
import Foundation
/// Class Frame.
public class Frame {
/// 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_Frame(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_Frame(&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 backgroundColor: Color {
get {
let result = _prop_get_CppbindExample_Frame_backgroundColor(cself)
guard let sctoswiftresult = Color(rawValue: result) else {
ExceptionHandler.handleUncaughtException(
"Internal error: unresolved reference to non existing field of Color enum.")
}
return sctoswiftresult
}
set(value) {
let swifttoscvalue = value.rawValue
_prop_set_CppbindExample_Frame_backgroundColor(cself, swifttoscvalue)
}
}
public var backgroundColorShade: ColorShade {
get {
let result = _prop_get_CppbindExample_Frame_backgroundColorShade(cself)
guard let sctoswiftresult = ColorShade(rawValue: result) else {
ExceptionHandler.handleUncaughtException(
"Internal error: unresolved reference to non existing field of ColorShade enum.")
}
return sctoswiftresult
}
set(value) {
let swifttoscvalue = value.rawValue
_prop_set_CppbindExample_Frame_backgroundColorShade(cself, swifttoscvalue)
}
}
public func getNextColor(color: Color) -> Color {
let swifttosccolor = color.rawValue
var cppbindErr = CppBindCObject()
let result = _func_CppbindExample_Frame_getNextColor(cself, swifttosccolor, &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
}
/// 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::Frame" }
}