From f616c4049c1d4b5ab2beaaa4473a9c62ea857183 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 31 Mar 2026 20:51:46 +0200 Subject: [PATCH] Add Codex-generated wrappergen --- cmake/CMakeLists.txt | 5 + src/wrappergen/CMakeLists.txt | 74 + src/wrappergen/__init__.py | 7 + src/wrappergen/clang_frontend.py | 605 ++++ src/wrappergen/config.py | 42 + src/wrappergen/conventions.py | 137 + src/wrappergen/emit.py | 877 ++++++ src/wrappergen/examples/print_walls.py | 25 + src/wrappergen/generate.py | 134 + .../generated/_ifcopenshell_experimental.cpp | 2616 +++++++++++++++++ .../generated/ifcopenshell_experimental.py | 525 ++++ .../ifcopenshell_experimental_c_api.cpp | 2253 ++++++++++++++ .../ifcopenshell_experimental_c_api.h | 241 ++ src/wrappergen/model.py | 74 + 14 files changed, 7615 insertions(+) create mode 100644 src/wrappergen/CMakeLists.txt create mode 100644 src/wrappergen/__init__.py create mode 100644 src/wrappergen/clang_frontend.py create mode 100644 src/wrappergen/config.py create mode 100644 src/wrappergen/conventions.py create mode 100644 src/wrappergen/emit.py create mode 100644 src/wrappergen/examples/print_walls.py create mode 100644 src/wrappergen/generate.py create mode 100644 src/wrappergen/generated/_ifcopenshell_experimental.cpp create mode 100644 src/wrappergen/generated/ifcopenshell_experimental.py create mode 100644 src/wrappergen/generated/ifcopenshell_experimental_c_api.cpp create mode 100644 src/wrappergen/generated/ifcopenshell_experimental_c_api.h create mode 100644 src/wrappergen/model.py diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f62a9813ff..65ce6e1d0e 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -63,6 +63,7 @@ option(NO_WARN "Disable all warnings" OFF) option(BUILD_IFCGEOM "Build IfcGeom." ON) option(BUILD_IFCPYTHON "Build IfcPython." ON) +option(BUILD_IFCPARSE_EXPERIMENTAL_WRAPPER "Build the experimental Clang-generated ifcparse Python wrapper." OFF) option(BUILD_CONVERT "Build IfcConvert executable." ON) option(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF) option(BUILD_EXAMPLES "Build example applications." ON) @@ -543,6 +544,10 @@ endif() add_subdirectory(../src/ifcparse ifcparse) set(IFCOPENSHELL_LIBRARIES IfcParse) +if(BUILD_IFCPARSE_EXPERIMENTAL_WRAPPER) + add_subdirectory(../src/wrappergen wrappergen) +endif() + if(BUILD_IFCGEOM) # CGAL::CGAL target already has dependencies resolved. if(WITH_CGAL AND CGAL_DIR) diff --git a/src/wrappergen/CMakeLists.txt b/src/wrappergen/CMakeLists.txt new file mode 100644 index 0000000000..cce10df035 --- /dev/null +++ b/src/wrappergen/CMakeLists.txt @@ -0,0 +1,74 @@ +set(IFCPARSE_WRAPPERGEN_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated") + +option(IFCPARSE_WRAPPERGEN_REGENERATE "Regenerate the experimental wrappergen outputs before building." OFF) + +if(IFCPARSE_WRAPPERGEN_REGENERATE) + find_package(Python COMPONENTS Interpreter REQUIRED) + set(IFCPARSE_WRAPPERGEN_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") + + add_custom_command( + OUTPUT + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental_c_api.h" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental_c_api.cpp" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/_ifcopenshell_experimental.cpp" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental.py" + COMMAND ${CMAKE_COMMAND} -E make_directory "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}" + COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/generate.py" + --repo-root "${PROJECT_SOURCE_DIR}/.." + --output-dir "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}" + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/generate.py" + "${CMAKE_CURRENT_SOURCE_DIR}/config.py" + "${CMAKE_CURRENT_SOURCE_DIR}/model.py" + "${CMAKE_CURRENT_SOURCE_DIR}/clang_frontend.py" + "${CMAKE_CURRENT_SOURCE_DIR}/emit.py" + "${CMAKE_CURRENT_SOURCE_DIR}/conventions.py" + "${PROJECT_SOURCE_DIR}/../src/ifcparse/file.h" + "${PROJECT_SOURCE_DIR}/../src/ifcparse/express.h" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Regenerating experimental ifcparse wrapper outputs" + VERBATIM + ) + + add_custom_target( + ifcopenshell_experimental_generate + DEPENDS + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental_c_api.h" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental_c_api.cpp" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/_ifcopenshell_experimental.cpp" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental.py" + ) +endif() + +find_package(Python COMPONENTS Development.Module REQUIRED) + +add_library(_ifcopenshell_experimental MODULE + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/ifcopenshell_experimental_c_api.cpp" + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}/_ifcopenshell_experimental.cpp" +) + +if(TARGET ifcopenshell_experimental_generate) + add_dependencies(_ifcopenshell_experimental ifcopenshell_experimental_generate) +endif() + +target_include_directories(_ifcopenshell_experimental PRIVATE + "${IFCPARSE_WRAPPERGEN_GENERATED_DIR}" + "${PROJECT_SOURCE_DIR}/../src/ifcparse" +) + +target_link_libraries(_ifcopenshell_experimental PRIVATE + IfcParse + Python::Module +) + +set_target_properties(_ifcopenshell_experimental PROPERTIES PREFIX "") + +if(WASM_BUILD) + set(PYTHON_EXTENSION_SUFFIX ".cpython-${Python_VERSION_MAJOR}${Python_VERSION_MINOR}-wasm32-emscripten.so") +elseif(WIN32) + set(PYTHON_EXTENSION_SUFFIX ".${Python_SOABI}.pyd") +else() + set(PYTHON_EXTENSION_SUFFIX ".${Python_SOABI}.so") +endif() + +set_target_properties(_ifcopenshell_experimental PROPERTIES SUFFIX "${PYTHON_EXTENSION_SUFFIX}") diff --git a/src/wrappergen/__init__.py b/src/wrappergen/__init__.py new file mode 100644 index 0000000000..5db22be2cc --- /dev/null +++ b/src/wrappergen/__init__.py @@ -0,0 +1,7 @@ +from .config import CompilationConfig, IgnoreConfig, WrapperConfig + +__all__ = [ + "CompilationConfig", + "IgnoreConfig", + "WrapperConfig", +] diff --git a/src/wrappergen/clang_frontend.py b/src/wrappergen/clang_frontend.py new file mode 100644 index 0000000000..351bcd91bd --- /dev/null +++ b/src/wrappergen/clang_frontend.py @@ -0,0 +1,605 @@ +from __future__ import annotations + +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path + +from .config import WrapperConfig +from .conventions import ( + cpp_leaf_name, + enum_adapter_name, + handle_adapter_name, + is_enum_adapter, + normalize_cpp_type, + normalize_identifier, + pascal_case, + resolve_cpp_type_key, + safe_python_identifier, + sequence_adapter_name, + strip_pointer, +) +from .model import CallableModel, ClassModel, EnumModel, EnumValueModel, ModuleModel, ParameterModel + + +def _require_clang(): + try: + from clang import cindex + except ImportError as exc: + raise RuntimeError( + "clang.cindex is required for wrapper generation. Install the Clang Python bindings " + "and ensure libclang is discoverable before rerunning the generator." + ) from exc + return cindex + + +@dataclass(slots=True) +class _ParameterSpec: + has_default: bool + default_cpp_value: str | None + + +def _iter_children(cursor): + for child in cursor.get_children(): + yield child + yield from _iter_children(child) + + +def _qualified_name(cursor) -> str: + cindex = _require_clang() + accepted = { + cindex.CursorKind.NAMESPACE, + cindex.CursorKind.CLASS_DECL, + cindex.CursorKind.STRUCT_DECL, + cindex.CursorKind.ENUM_DECL, + } + names: list[str] = [] + current = cursor + while current is not None and current.kind != cindex.CursorKind.TRANSLATION_UNIT: + if current.kind in accepted and current.spelling: + names.append(current.spelling) + current = current.semantic_parent + return "::".join(reversed(names)) + + +def _join_cpp_tokens(tokens: list[str]) -> str: + return "".join(tokens).strip() + + +def _parse_parameter_specs(cursor) -> list[_ParameterSpec]: + parameters = list(cursor.get_arguments()) + if not parameters: + return [] + + tokens = [token.spelling for token in cursor.get_tokens()] + try: + start = tokens.index("(") + 1 + except ValueError: + return [_ParameterSpec(False, None) for _ in parameters] + + depth = 0 + current: list[str] = [] + groups: list[list[str]] = [] + for token in tokens[start:]: + if token in {"(", "<", "["}: + depth += 1 + elif token in {")", ">", "]"}: + if token == ")" and depth == 0: + if current: + groups.append(current[:]) + break + depth = max(depth - 1, 0) + elif token == "," and depth == 0: + groups.append(current[:]) + current = [] + continue + current.append(token) + if current: + groups.append(current) + + specs: list[_ParameterSpec] = [] + for index, _ in enumerate(parameters): + group = groups[index] if index < len(groups) else [] + if "=" not in group: + specs.append(_ParameterSpec(False, None)) + continue + equals = group.index("=") + default_tokens = group[equals + 1 :] + specs.append(_ParameterSpec(True, _join_cpp_tokens(default_tokens) or None)) + return specs + + +def _build_translation_unit(config: WrapperConfig, header: Path): + cindex = _require_clang() + index = cindex.Index.create() + arguments: list[str] = [] + if config.compilation.compile_commands: + database = cindex.CompilationDatabase.fromDirectory(str(Path(config.compilation.compile_commands).resolve())) + candidates = [header.with_suffix(".cpp"), header.with_suffix(".cc"), header.with_suffix(".cxx")] + for candidate in candidates: + commands = database.getCompileCommands(str(candidate.resolve())) + if not commands: + continue + command = list(commands[0].arguments) + filtered: list[str] = [] + skip_next = False + for argument in command[1:]: + if skip_next: + skip_next = False + continue + if argument in {"-c", "/c"}: + continue + if argument in {"-o", "/Fo", "/Fd"}: + skip_next = True + continue + if argument.endswith((".cpp", ".cc", ".cxx", ".c")): + continue + filtered.append(argument) + arguments.extend(filtered) + break + if not arguments: + arguments.extend(config.compilation.clang_args) + arguments.extend(f"-I{Path(include_dir).resolve()}" for include_dir in config.compilation.include_dirs) + arguments.extend(f"-D{define}" for define in config.compilation.defines) + return index.parse(str(header.resolve()), args=arguments) + + +def _cursor_file_path(cursor) -> Path | None: + file = cursor.location.file + if file is None: + return None + try: + return Path(file.name).resolve() + except OSError: + return None + + +def _is_in_allowed_headers(cursor, allowed_headers: set[Path]) -> bool: + path = _cursor_file_path(cursor) + return path in allowed_headers if path is not None else False + + +def _is_in_allowed_namespace(cpp_name: str, config: WrapperConfig) -> bool: + if not config.allowed_namespaces: + return True + return any(cpp_name == namespace or cpp_name.startswith(f"{namespace}::") for namespace in config.allowed_namespaces) + + +def _matches_ignore(cpp_name: str, ignored: list[str]) -> bool: + return cpp_name in ignored + + +def _matches_ignored_namespace(cpp_name: str, ignored_namespaces: list[str]) -> bool: + return any(cpp_name == namespace or cpp_name.startswith(f"{namespace}::") for namespace in ignored_namespaces) + + +def _has_export_macro(cursor, macro_name: str) -> bool: + return any(token.spelling == macro_name for token in cursor.get_tokens()) + + +def _is_top_level_type(cursor) -> bool: + cindex = _require_clang() + parent = cursor.semantic_parent + return parent is not None and parent.kind in {cindex.CursorKind.TRANSLATION_UNIT, cindex.CursorKind.NAMESPACE} + + +def _collect_enum_cursors(translation_units, config: WrapperConfig, allowed_headers: set[Path]) -> dict[str, object]: + cindex = _require_clang() + enums: dict[str, object] = {} + for translation_unit in translation_units: + for cursor in _iter_children(translation_unit.cursor): + if cursor.kind != cindex.CursorKind.ENUM_DECL: + continue + if not cursor.is_definition(): + continue + if not _is_top_level_type(cursor): + continue + if not _is_in_allowed_headers(cursor, allowed_headers): + continue + cpp_name = _qualified_name(cursor) + if not cpp_name or not _is_in_allowed_namespace(cpp_name, config): + continue + if _matches_ignored_namespace(cpp_name, config.ignore.namespaces): + continue + if _matches_ignore(cpp_name, config.ignore.enums): + continue + enums[normalize_cpp_type(cpp_name)] = cursor + return enums + + +def _collect_class_cursors(translation_units, config: WrapperConfig, allowed_headers: set[Path]) -> dict[str, object]: + cindex = _require_clang() + classes: dict[str, object] = {} + for translation_unit in translation_units: + for cursor in _iter_children(translation_unit.cursor): + if cursor.kind not in {cindex.CursorKind.CLASS_DECL, cindex.CursorKind.STRUCT_DECL}: + continue + if not cursor.is_definition(): + continue + if not _is_top_level_type(cursor): + continue + if not _is_in_allowed_headers(cursor, allowed_headers): + continue + cpp_name = _qualified_name(cursor) + if not cpp_name or not _is_in_allowed_namespace(cpp_name, config): + continue + if _matches_ignored_namespace(cpp_name, config.ignore.namespaces): + continue + if _matches_ignore(cpp_name, config.ignore.classes): + continue + if config.require_exported_classes and not _has_export_macro(cursor, config.export_macro): + continue + classes[normalize_cpp_type(cpp_name)] = cursor + return classes + + +def _normalized_type_adapters(config: WrapperConfig) -> dict[str, str]: + return {normalize_cpp_type(cpp_type): adapter for cpp_type, adapter in config.type_adapters.items()} + + +def _python_class_name(cpp_name: str, config: WrapperConfig) -> str: + return config.class_names.get(cpp_name, cpp_leaf_name(cpp_name)) + + +def _python_enum_name(cpp_name: str, config: WrapperConfig) -> str: + return config.enum_names.get(cpp_name, pascal_case(cpp_leaf_name(cpp_name))) + + +def _parameter_python_name(raw_name: str, index: int, config: WrapperConfig) -> str: + source = raw_name or f"arg{index}" + return safe_python_identifier(normalize_identifier(config.parameter_names.get(source, source))) + + +def _owner_cpp_name(cpp_name: str, config: WrapperConfig) -> str | None: + return config.class_owner_types.get(cpp_name) + + +def _handle_kind(cpp_name: str, config: WrapperConfig) -> str: + return config.class_handle_kinds.get(cpp_name, config.default_class_handle_kind) + + +def _resolve_parameter_adapter( + cpp_type: str, + scalar_adapters: dict[str, str], + enum_cursors: dict[str, object], +) -> str | None: + canonical = normalize_cpp_type(cpp_type) + if canonical in scalar_adapters: + return scalar_adapters[canonical] + enum_key = resolve_cpp_type_key(cpp_type, set(enum_cursors)) + if enum_key is not None: + return enum_adapter_name(enum_key) + return None + + +def _vector_inner_type(cpp_type: str) -> str | None: + canonical = normalize_cpp_type(cpp_type) + prefix = "std::vector<" + if not canonical.startswith(prefix) or not canonical.endswith(">"): + return None + return canonical[len(prefix) : -1] + + +def _resolve_return_adapter( + cpp_type: str, + scalar_adapters: dict[str, str], + enum_cursors: dict[str, object], + class_models_by_cpp: dict[str, ClassModel], +) -> str | None: + canonical = normalize_cpp_type(cpp_type) + if canonical in scalar_adapters: + return scalar_adapters[canonical] + enum_key = resolve_cpp_type_key(cpp_type, set(enum_cursors)) + if enum_key is not None: + return enum_adapter_name(enum_key) + vector_inner = _vector_inner_type(cpp_type) + if vector_inner: + sequence_key = resolve_cpp_type_key(vector_inner, set(class_models_by_cpp)) + if sequence_key is not None: + return sequence_adapter_name(sequence_key) + pointee = resolve_cpp_type_key(strip_pointer(cpp_type), set(class_models_by_cpp)) + if pointee is not None: + target = class_models_by_cpp[pointee] + if canonical.endswith("*") and target.handle_kind == "shared_ptr": + return None + return handle_adapter_name(pointee) + return None + + +def _python_default_value( + cpp_value: str | None, + adapter: str, + enum_py_names: dict[str, str], +) -> str | None: + if cpp_value is None: + return None + if adapter == "bool": + if cpp_value == "true": + return "True" + if cpp_value == "false": + return "False" + return None + if adapter == "integer": + return cpp_value if cpp_value.lstrip("-").isdigit() else None + if adapter == "string": + return cpp_value if cpp_value.startswith(("\"", "'")) else None + if is_enum_adapter(adapter): + enum_name = enum_py_names.get(adapter.split(":", 1)[1]) + if enum_name is None: + return None + return f"{enum_name}.{cpp_value.rsplit('::', 1)[-1]}" + return None + + +def _build_parameter_models( + cursor, + config: WrapperConfig, + scalar_adapters: dict[str, str], + enum_cursors: dict[str, object], +) -> list[ParameterModel] | None: + parameter_specs = _parse_parameter_specs(cursor) + parameter_models: list[ParameterModel] = [] + for index, parameter in enumerate(cursor.get_arguments()): + adapter = _resolve_parameter_adapter(parameter.type.spelling, scalar_adapters, enum_cursors) + if adapter is None: + return None + spec = parameter_specs[index] if index < len(parameter_specs) else _ParameterSpec(False, None) + parameter_models.append( + ParameterModel( + name=_parameter_python_name(parameter.spelling, index, config), + cpp_name=parameter.spelling or f"arg{index}", + cpp_type=parameter.type.spelling, + adapter=adapter, + has_default=spec.has_default, + default_cpp_value=spec.default_cpp_value, + ) + ) + return parameter_models + + +def _is_deleted(cursor) -> bool: + tokens = [token.spelling for token in cursor.get_tokens()] + return "=" in tokens and "delete" in tokens + + +def _is_copy_or_move_constructor(cursor, owner_cpp_name: str) -> bool: + parameters = list(cursor.get_arguments()) + if len(parameters) != 1: + return False + return strip_pointer(parameters[0].type.spelling) == normalize_cpp_type(owner_cpp_name) + + +def _constructor_py_name(parameters: list[ParameterModel], minimum_arity: int) -> str: + if minimum_arity == 0: + return "create" + required = parameters[:minimum_arity] + suffix = "_".join(parameter.name for parameter in required) + return safe_python_identifier(f"with_{suffix}") + + +def _finalize_overload_names(callables: list[CallableModel]) -> None: + groups: dict[str, list[CallableModel]] = defaultdict(list) + for callable_model in callables: + groups[callable_model.py_name].append(callable_model) + for group in groups.values(): + if len(group) == 1: + continue + for index, callable_model in enumerate(group, start=1): + parameter_suffix = "_".join(parameter.name for parameter in callable_model.parameters) + if callable_model.kind == "constructor": + callable_model.py_name = f"{callable_model.py_name}_{parameter_suffix}" if parameter_suffix else f"{callable_model.py_name}_overload_{index}" + else: + callable_model.py_name = f"{callable_model.py_name}_with_{parameter_suffix}" if parameter_suffix else f"{callable_model.py_name}_overload_{index}" + callable_model.c_name = normalize_identifier(callable_model.py_name) + + +def _deduplicate_callables(callables: list[CallableModel]) -> list[CallableModel]: + unique: list[CallableModel] = [] + seen: set[tuple[str, str, str, tuple[str, ...]]] = set() + for callable_model in callables: + key = ( + callable_model.kind, + callable_model.cpp_name, + callable_model.return_adapter, + tuple(normalize_cpp_type(parameter.cpp_type) for parameter in callable_model.parameters), + ) + if key in seen: + continue + seen.add(key) + unique.append(callable_model) + return unique + + +def _discover_constructors( + class_cursor, + owner: ClassModel, + config: WrapperConfig, + scalar_adapters: dict[str, str], + enum_cursors: dict[str, object], +) -> list[CallableModel]: + cindex = _require_clang() + constructors: list[CallableModel] = [] + for child in class_cursor.get_children(): + if child.kind != cindex.CursorKind.CONSTRUCTOR: + continue + if child.access_specifier != cindex.AccessSpecifier.PUBLIC: + continue + if _is_deleted(child) or _is_copy_or_move_constructor(child, owner.cpp_name): + continue + parameters = _build_parameter_models(child, config, scalar_adapters, enum_cursors) + if parameters is None: + continue + callable_model = CallableModel( + kind="constructor", + owner_cpp_name=owner.cpp_name, + owner_py_name=owner.py_name, + cpp_name=cpp_leaf_name(owner.cpp_name), + py_name="create", + c_name="new", + return_cpp_type=owner.cpp_name, + return_adapter=handle_adapter_name(owner.cpp_name), + parameters=parameters, + ) + callable_model.py_name = _constructor_py_name(parameters, callable_model.minimum_arity) + constructors.append(callable_model) + return constructors + + +def _discover_methods( + class_cursor, + owner: ClassModel, + config: WrapperConfig, + scalar_adapters: dict[str, str], + enum_cursors: dict[str, object], + class_models_by_cpp: dict[str, ClassModel], +) -> list[CallableModel]: + cindex = _require_clang() + methods: list[CallableModel] = [] + for child in class_cursor.get_children(): + if child.kind != cindex.CursorKind.CXX_METHOD: + continue + if child.access_specifier != cindex.AccessSpecifier.PUBLIC: + continue + if child.spelling.startswith("operator") or _is_deleted(child): + continue + if child.is_static_method(): + continue + qualified_name = f"{owner.cpp_name}::{child.spelling}" + if _matches_ignore(qualified_name, config.ignore.methods): + continue + return_adapter = _resolve_return_adapter(child.result_type.spelling, scalar_adapters, enum_cursors, class_models_by_cpp) + if return_adapter is None: + continue + parameters = _build_parameter_models(child, config, scalar_adapters, enum_cursors) + if parameters is None: + continue + methods.append( + CallableModel( + kind="method", + owner_cpp_name=owner.cpp_name, + owner_py_name=owner.py_name, + cpp_name=child.spelling, + py_name=safe_python_identifier(normalize_identifier(child.spelling)), + c_name=normalize_identifier(child.spelling), + return_cpp_type=child.result_type.spelling, + return_adapter=return_adapter, + parameters=parameters, + ) + ) + return methods + + +def _build_enum_model(cpp_name: str, cursor, config: WrapperConfig) -> EnumModel: + py_name = _python_enum_name(cpp_name, config) + c_name = default_c_name = f"{config.c_prefix}_{normalize_identifier(py_name)}_t" + values: list[EnumValueModel] = [] + for child in cursor.get_children(): + if child.spelling: + values.append( + EnumValueModel( + name=child.spelling, + c_name=f"{default_c_name.upper()}_{child.spelling}", + value=child.enum_value, + ) + ) + return EnumModel(cpp_name=cpp_name, py_name=py_name, c_name=c_name, values=values) + + +def build_module_model(config: WrapperConfig) -> ModuleModel: + translation_units = [_build_translation_unit(config, Path(header)) for header in config.compilation.headers] + allowed_headers = {Path(header).resolve() for header in config.compilation.headers} + + enum_cursors = _collect_enum_cursors(translation_units, config, allowed_headers) + class_cursors = _collect_class_cursors(translation_units, config, allowed_headers) + scalar_adapters = _normalized_type_adapters(config) + + class_models_by_cpp: dict[str, ClassModel] = {} + for normalized_cpp_name, cursor in class_cursors.items(): + cpp_name = _qualified_name(cursor) + owner_cpp_name = _owner_cpp_name(cpp_name, config) + owner_py_name = _python_class_name(owner_cpp_name, config) if owner_cpp_name else None + class_models_by_cpp[normalized_cpp_name] = ClassModel( + cpp_name=cpp_name, + py_name=_python_class_name(cpp_name, config), + handle_kind=_handle_kind(cpp_name, config), + owner_cpp_name=owner_cpp_name, + owner_py_name=owner_py_name, + ) + + for normalized_cpp_name, cursor in class_cursors.items(): + owner = class_models_by_cpp[normalized_cpp_name] + owner.callables.extend(_discover_constructors(cursor, owner, config, scalar_adapters, enum_cursors)) + owner.callables.extend(_discover_methods(cursor, owner, config, scalar_adapters, enum_cursors, class_models_by_cpp)) + owner.callables = _deduplicate_callables(owner.callables) + _finalize_overload_names(owner.callables) + + used_class_names: set[str] = set() + used_enum_names: set[str] = set() + for class_model in class_models_by_cpp.values(): + if class_model.callables: + used_class_names.add(normalize_cpp_type(class_model.cpp_name)) + if class_model.owner_cpp_name: + used_class_names.add(normalize_cpp_type(class_model.owner_cpp_name)) + for callable_model in class_model.callables: + if is_enum_adapter(callable_model.return_adapter): + used_enum_names.add(callable_model.return_adapter.split(":", 1)[1]) + if callable_model.return_adapter.startswith("handle:"): + used_class_names.add(callable_model.return_adapter.split(":", 1)[1]) + if callable_model.return_adapter.startswith("sequence:"): + used_class_names.add(callable_model.return_adapter.split(":", 1)[1]) + for parameter in callable_model.parameters: + if is_enum_adapter(parameter.adapter): + used_enum_names.add(parameter.adapter.split(":", 1)[1]) + + selected_classes: list[ClassModel] = [] + for normalized_cpp_name, class_model in class_models_by_cpp.items(): + if normalized_cpp_name in used_class_names: + selected_classes.append(class_model) + + enum_models_by_cpp: dict[str, EnumModel] = {} + for normalized_cpp_name in sorted(used_enum_names): + cursor = enum_cursors.get(normalized_cpp_name) + if cursor is None: + continue + cpp_name = _qualified_name(cursor) + enum_models_by_cpp[normalized_cpp_name] = _build_enum_model(cpp_name, cursor, config) + + enum_py_names = {normalized_cpp_name: model.py_name for normalized_cpp_name, model in enum_models_by_cpp.items()} + for class_model in selected_classes: + for callable_model in class_model.callables: + for parameter in callable_model.parameters: + if parameter.has_default: + parameter.default_python_value = _python_default_value( + parameter.default_cpp_value, + parameter.adapter, + enum_py_names, + ) + + if not any(class_model.callables for class_model in selected_classes): + raise RuntimeError("No supported public classes or methods were discovered in the configured headers") + + source_headers: list[str] = [] + seen_headers: set[str] = set() + for class_model in selected_classes: + cursor = class_cursors.get(normalize_cpp_type(class_model.cpp_name)) + header = _cursor_file_path(cursor) if cursor is not None else None + if header is not None and header.name not in seen_headers: + seen_headers.add(header.name) + source_headers.append(header.name) + for normalized_cpp_name in enum_models_by_cpp: + cursor = enum_cursors.get(normalized_cpp_name) + header = _cursor_file_path(cursor) if cursor is not None else None + if header is not None and header.name not in seen_headers: + seen_headers.add(header.name) + source_headers.append(header.name) + + return ModuleModel( + module_name=config.module_name, + c_prefix=config.c_prefix, + api_header_name=config.api_header_name, + api_implementation_name=config.api_implementation_name, + extension_source_name=config.extension_source_name, + python_source_name=config.python_source_name, + source_headers=source_headers, + classes=selected_classes, + enums=list(enum_models_by_cpp.values()), + ) diff --git a/src/wrappergen/config.py b/src/wrappergen/config.py new file mode 100644 index 0000000000..aea6cfbc69 --- /dev/null +++ b/src/wrappergen/config.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from dataclasses import dataclass, field + + +@dataclass(slots=True) +class CompilationConfig: + headers: list[str] + clang_args: list[str] = field(default_factory=lambda: ["-x", "c++", "-std=c++17"]) + include_dirs: list[str] = field(default_factory=list) + defines: list[str] = field(default_factory=list) + compile_commands: str | None = None + + +@dataclass(slots=True) +class IgnoreConfig: + namespaces: list[str] = field(default_factory=list) + classes: list[str] = field(default_factory=list) + enums: list[str] = field(default_factory=list) + methods: list[str] = field(default_factory=list) + + +@dataclass(slots=True) +class WrapperConfig: + module_name: str + c_prefix: str + api_header_name: str + api_implementation_name: str + extension_source_name: str + python_source_name: str + compilation: CompilationConfig + allowed_namespaces: list[str] = field(default_factory=list) + export_macro: str = "IFC_PARSE_API" + require_exported_classes: bool = True + default_class_handle_kind: str = "value" + class_names: dict[str, str] = field(default_factory=dict) + enum_names: dict[str, str] = field(default_factory=dict) + parameter_names: dict[str, str] = field(default_factory=dict) + class_handle_kinds: dict[str, str] = field(default_factory=dict) + class_owner_types: dict[str, str] = field(default_factory=dict) + type_adapters: dict[str, str] = field(default_factory=dict) + ignore: IgnoreConfig = field(default_factory=IgnoreConfig) diff --git a/src/wrappergen/conventions.py b/src/wrappergen/conventions.py new file mode 100644 index 0000000000..401c329daa --- /dev/null +++ b/src/wrappergen/conventions.py @@ -0,0 +1,137 @@ +from __future__ import annotations + +import keyword +import re + + +INTEGER_CPP_TYPES = {"int", "size_t", "std::size_t", "unsigned int", "uint32_t"} + + +def normalize_identifier(name: str) -> str: + result: list[str] = [] + previous_was_lower = False + for character in name: + if character.isupper() and previous_was_lower: + result.append("_") + result.append(character.lower() if character.isalnum() else "_") + previous_was_lower = character.islower() or character.isdigit() + normalized = "".join(result).strip("_") + while "__" in normalized: + normalized = normalized.replace("__", "_") + return normalized + + +def cpp_leaf_name(cpp_name: str) -> str: + return cpp_name.rsplit("::", 1)[-1] + + +def pascal_case(name: str) -> str: + parts = [part for part in re.split(r"[_\W]+", name) if part] + if parts: + return "".join(part[:1].upper() + part[1:] for part in parts) + return name[:1].upper() + name[1:] if name else name + + +def safe_python_identifier(name: str) -> str: + return f"{name}_" if keyword.iskeyword(name) else name + + +def normalize_cpp_type(cpp_type: str) -> str: + normalized = cpp_type.replace("class ", "").replace("struct ", "").replace("enum ", "") + normalized = normalized.replace("std::basic_string", "std::string") + normalized = normalized.replace("std::__cxx11::basic_string", "std::string") + normalized = re.sub(r"\b(const|volatile)\b", " ", normalized) + normalized = normalized.replace("&", " ") + normalized = re.sub(r"\s+", "", normalized) + return normalized + + +def strip_pointer(cpp_type: str) -> str: + normalized = normalize_cpp_type(cpp_type) + while normalized.endswith("*"): + normalized = normalized[:-1] + return normalized + + +def c_identifier_from_cpp_name(cpp_name: str, c_prefix: str | None = None) -> str: + parts = [part for part in cpp_name.split("::") if part] + if c_prefix and parts and normalize_identifier(parts[0]) == normalize_identifier(c_prefix): + parts = parts[1:] + return normalize_identifier("_".join(parts)) + + +def default_enum_c_name(c_prefix: str, py_name: str) -> str: + return f"{c_prefix}_{normalize_identifier(py_name)}_t" + + +def default_enum_value_c_name(enum_c_name: str, value_name: str) -> str: + return f"{enum_c_name.upper()}_{value_name}" + + +def handle_adapter_name(cpp_name: str) -> str: + return f"handle:{normalize_cpp_type(cpp_name)}" + + +def is_handle_adapter(adapter: str) -> bool: + return adapter.startswith("handle:") + + +def handle_adapter_target(adapter: str) -> str: + return adapter.split(":", 1)[1] + + +def enum_adapter_name(cpp_name: str) -> str: + return f"enum:{normalize_cpp_type(cpp_name)}" + + +def is_enum_adapter(adapter: str) -> bool: + return adapter.startswith("enum:") + + +def enum_adapter_target(adapter: str) -> str: + return adapter.split(":", 1)[1] + + +def sequence_adapter_name(cpp_name: str) -> str: + return f"sequence:{normalize_cpp_type(cpp_name)}" + + +def is_sequence_adapter(adapter: str) -> bool: + return adapter.startswith("sequence:") + + +def sequence_adapter_target(adapter: str) -> str: + return adapter.split(":", 1)[1] + + +def cpp_type_lists_match(actual_types: list[str], expected_types: list[str]) -> bool: + if len(actual_types) != len(expected_types): + return False + return all(cpp_types_equivalent(actual, expected) for actual, expected in zip(actual_types, expected_types)) + + +def cpp_types_equivalent(actual_type: str, expected_type: str) -> bool: + actual = normalize_cpp_type(actual_type) + expected = normalize_cpp_type(expected_type) + if actual == expected: + return True + if "<" in actual or "<" in expected: + return False + actual_leaf = strip_pointer(actual).rsplit("::", 1)[-1] + expected_leaf = strip_pointer(expected).rsplit("::", 1)[-1] + return actual_leaf == expected_leaf + + +def resolve_cpp_type_key(cpp_type: str, candidates: set[str]) -> str | None: + canonical = normalize_cpp_type(cpp_type) + if canonical in candidates: + return canonical + leaf = strip_pointer(canonical).rsplit("::", 1)[-1] + matches = [ + candidate + for candidate in candidates + if strip_pointer(candidate).rsplit("::", 1)[-1] == leaf + ] + if len(matches) == 1: + return matches[0] + return None diff --git a/src/wrappergen/emit.py b/src/wrappergen/emit.py new file mode 100644 index 0000000000..1ffbbf8cd3 --- /dev/null +++ b/src/wrappergen/emit.py @@ -0,0 +1,877 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path + +from .conventions import ( + c_identifier_from_cpp_name, + enum_adapter_target, + handle_adapter_target, + is_enum_adapter, + is_handle_adapter, + is_sequence_adapter, + normalize_cpp_type, + normalize_identifier, + sequence_adapter_target, +) +from .model import CallableModel, ClassModel, EnumModel, ModuleModel, ParameterModel + + +def _class_index(model: ModuleModel) -> dict[str, ClassModel]: + return {normalize_cpp_type(class_model.cpp_name): class_model for class_model in model.classes} + + +def _enum_index(model: ModuleModel) -> dict[str, EnumModel]: + return {normalize_cpp_type(enum_model.cpp_name): enum_model for enum_model in model.enums} + + +def _class_c_type(class_model: ClassModel, model: ModuleModel) -> str: + return f"{model.c_prefix}_{_class_c_identifier(class_model, model)}_t" + + +def _list_c_type(class_model: ClassModel, model: ModuleModel) -> str: + return f"{model.c_prefix}_{_class_c_identifier(class_model, model)}_list_t" + + +def _class_c_identifier(class_model: ClassModel, model: ModuleModel) -> str: + return c_identifier_from_cpp_name(class_model.cpp_name, model.c_prefix) + + +def _capsule_name_symbol(class_model: ClassModel) -> str: + return f"{normalize_identifier(class_model.cpp_name).upper()}_CAPSULE_NAME" + + +def _capsule_destructor_name(class_model: ClassModel) -> str: + return f"{normalize_identifier(class_model.cpp_name)}_capsule_destructor" + + +def _parameter_names(parameters: list[ParameterModel]) -> str: + return "_".join(normalize_identifier(parameter.name) for parameter in parameters) + + +def _api_owner_identifier(owner: ClassModel) -> str: + root_namespace = owner.cpp_name.split("::", 1)[0] if "::" in owner.cpp_name else None + return c_identifier_from_cpp_name(owner.cpp_name, root_namespace) + + +@dataclass(slots=True) +class CallableVariant: + owner: ClassModel + callable: CallableModel + api_name: str + parameters: list[ParameterModel] + + +def _expand_variants(owner: ClassModel, callable_model: CallableModel) -> list[CallableVariant]: + required = callable_model.minimum_arity + variants: list[CallableVariant] = [] + for arity in range(required, len(callable_model.parameters) + 1): + included = callable_model.parameters[:arity] + api_name = f"{_api_owner_identifier(owner)}_{callable_model.c_name}" + if callable_model.kind == "constructor": + required_parameters = callable_model.parameters[:required] + optional_parameters = callable_model.parameters[required:arity] + if required_parameters: + api_name += f"_with_{_parameter_names(required_parameters)}" + if optional_parameters: + api_name += f"_with_{_parameter_names(optional_parameters)}" + elif required < len(callable_model.parameters): + optional_parameters = callable_model.parameters[required:arity] + if optional_parameters: + api_name += f"_with_{_parameter_names(optional_parameters)}" + variants.append( + CallableVariant( + owner=owner, + callable=callable_model, + api_name=api_name, + parameters=included, + ) + ) + return variants or [ + CallableVariant( + owner=owner, + callable=callable_model, + api_name=f"{_api_owner_identifier(owner)}_{callable_model.c_name}", + parameters=callable_model.parameters, + ) + ] + + +def _all_variants(model: ModuleModel) -> list[CallableVariant]: + variants: list[CallableVariant] = [] + for owner in model.classes: + for callable_model in owner.callables: + variants.extend(_expand_variants(owner, callable_model)) + return variants + + +def _full_variant(owner: ClassModel, callable_model: CallableModel) -> CallableVariant: + return _expand_variants(owner, callable_model)[-1] + + +def _sequence_targets(model: ModuleModel) -> list[ClassModel]: + class_models = _class_index(model) + seen: set[str] = set() + results: list[ClassModel] = [] + for owner in model.classes: + for callable_model in owner.callables: + if is_sequence_adapter(callable_model.return_adapter): + target = sequence_adapter_target(callable_model.return_adapter) + if target not in seen: + seen.add(target) + results.append(class_models[target]) + return results + + +def _enum_c_type(adapter: str, model: ModuleModel) -> str: + enum_model = _enum_index(model).get(enum_adapter_target(adapter)) + if enum_model is None: + raise RuntimeError(f"Unable to resolve enum adapter '{adapter}'") + return enum_model.c_name + + +def _return_c_type(adapter: str, model: ModuleModel) -> str: + if adapter == "string": + return "char*" + if adapter == "integer": + return "int" + if adapter == "bool": + return "bool" + if adapter == "void": + return "void" + if is_enum_adapter(adapter): + return _enum_c_type(adapter, model) + if is_handle_adapter(adapter): + return f"{_class_c_type(_class_index(model)[handle_adapter_target(adapter)], model)}*" + if is_sequence_adapter(adapter): + return f"{_list_c_type(_class_index(model)[sequence_adapter_target(adapter)], model)}*" + raise RuntimeError(f"Unsupported return adapter: {adapter}") + + +def _parameter_c_type(parameter: ParameterModel, model: ModuleModel) -> str: + if parameter.adapter == "string": + return "const char*" + if parameter.adapter == "integer": + return "int" + if parameter.adapter == "bool": + return "bool" + if is_enum_adapter(parameter.adapter): + return _enum_c_type(parameter.adapter, model) + if is_handle_adapter(parameter.adapter): + target = _class_index(model)[handle_adapter_target(parameter.adapter)] + return f"{_class_c_type(target, model)}*" + raise RuntimeError(f"Unsupported parameter adapter: {parameter.adapter}") + + +def _class_or_enum_cpp_name(adapter: str, model: ModuleModel) -> str: + if is_handle_adapter(adapter): + return _class_index(model)[handle_adapter_target(adapter)].cpp_name + if is_enum_adapter(adapter): + return _enum_index(model)[enum_adapter_target(adapter)].cpp_name + raise RuntimeError(f"Adapter '{adapter}' does not resolve to a named C++ type") + + +def _cpp_argument(parameter: ParameterModel, model: ModuleModel) -> str: + if parameter.adapter == "string": + return f"std::string({parameter.name} ? {parameter.name} : \"\")" + if is_enum_adapter(parameter.adapter): + return f"static_cast<{_class_or_enum_cpp_name(parameter.adapter, model)}>({parameter.name})" + if is_handle_adapter(parameter.adapter): + target = _class_index(model)[handle_adapter_target(parameter.adapter)] + actual_type = normalize_cpp_type(parameter.cpp_type) + if actual_type.endswith("*"): + if target.handle_kind == "shared_ptr": + return f"{parameter.name}->value.get()" + return f"&{parameter.name}->value" + if target.handle_kind == "shared_ptr": + return f"*{parameter.name}->value" + return f"{parameter.name}->value" + return parameter.name + + +def _call_expression(variant: CallableVariant, model: ModuleModel) -> str: + arguments = ", ".join(_cpp_argument(parameter, model) for parameter in variant.parameters) + if variant.callable.kind == "constructor": + if variant.owner.handle_kind == "shared_ptr": + return f"std::make_shared<{variant.owner.cpp_name}>({arguments})" + return f"{variant.owner.cpp_name}({arguments})" + access = "handle->value->" if variant.owner.handle_kind == "shared_ptr" else "handle->value." + return f"{access}{variant.callable.cpp_name}({arguments})" + + +def _vector_inner_type(cpp_type: str) -> str | None: + canonical = normalize_cpp_type(cpp_type) + prefix = "std::vector<" + if not canonical.startswith(prefix) or not canonical.endswith(">"): + return None + return canonical[len(prefix) : -1] + + +def _owner_expression(source: ClassModel, target: ClassModel) -> str: + if target.owner_cpp_name is None: + raise RuntimeError(f"Class '{target.cpp_name}' does not declare an owner relationship") + if normalize_cpp_type(source.cpp_name) == normalize_cpp_type(target.owner_cpp_name): + if source.handle_kind != "shared_ptr": + raise RuntimeError(f"Owner class '{source.cpp_name}' must use shared_ptr handle storage") + return "handle->value" + if source.owner_cpp_name and normalize_cpp_type(source.owner_cpp_name) == normalize_cpp_type(target.owner_cpp_name): + return "handle->owner" + raise RuntimeError( + f"Unable to propagate owner '{target.owner_cpp_name}' from '{source.cpp_name}' to '{target.cpp_name}'" + ) + + +def _emit_handle_return_lines( + lines: list[str], + source_owner: ClassModel, + target: ClassModel, + callable_model: CallableModel, + call_expression: str, + model: ModuleModel, +) -> None: + normalized_return = normalize_cpp_type(callable_model.return_cpp_type) + if normalized_return.endswith("*"): + lines.append(f" auto result_ptr = {call_expression};") + lines.append(" if (result_ptr == nullptr) {") + lines.append(" return nullptr;") + lines.append(" }") + lines.append(" auto result = *result_ptr;") + else: + lines.append(f" auto result = {call_expression};") + if target.handle_kind == "shared_ptr": + lines.append(f" auto wrapped_value = std::make_shared<{target.cpp_name}>(std::move(result));") + lines.append(f" return new {_class_c_type(target, model)}{{ std::move(wrapped_value) }};") + return + if target.owner_cpp_name is not None: + owner_expression = "{}" if callable_model.kind == "constructor" else _owner_expression(source_owner, target) + lines.append(f" return new {_class_c_type(target, model)}{{ {owner_expression}, std::move(result) }};") + return + lines.append(f" return new {_class_c_type(target, model)}{{ std::move(result) }};") + + +def _emit_sequence_return_lines( + lines: list[str], + source_owner: ClassModel, + target: ClassModel, + callable_model: CallableModel, + call_expression: str, + model: ModuleModel, +) -> None: + vector_inner = _vector_inner_type(callable_model.return_cpp_type) + if vector_inner is not None and vector_inner.endswith("*"): + lines.append(f" auto source_result = {call_expression};") + lines.append(f" std::vector<{target.cpp_name}> result;") + lines.append(" result.reserve(source_result.size());") + lines.append(" for (const auto* item : source_result) {") + lines.append(" if (item != nullptr) {") + lines.append(" result.push_back(*item);") + lines.append(" }") + lines.append(" }") + else: + lines.append(f" auto result = {call_expression};") + if target.owner_cpp_name is not None: + owner_expression = _owner_expression(source_owner, target) + lines.append(f" return new {_list_c_type(target, model)}{{ {owner_expression}, std::move(result) }};") + return + lines.append(f" return new {_list_c_type(target, model)}{{ std::move(result) }};") + + +def emit_c_api_header(model: ModuleModel) -> str: + sequence_targets = _sequence_targets(model) + lines = [ + "#ifndef IFCOPENSHELL_EXPERIMENTAL_C_API_H", + "#define IFCOPENSHELL_EXPERIMENTAL_C_API_H", + "", + "#include ", + "#include ", + "", + "#ifdef __cplusplus", + 'extern "C" {', + "#endif", + "", + ] + for class_model in model.classes: + lines.append(f"typedef struct {_class_c_type(class_model, model)} {_class_c_type(class_model, model)};") + if model.classes: + lines.append("") + for class_model in sequence_targets: + lines.append(f"typedef struct {_list_c_type(class_model, model)} {_list_c_type(class_model, model)};") + if sequence_targets: + lines.append("") + for enum_model in model.enums: + lines.append(f"typedef enum {enum_model.c_name} {{") + for value in enum_model.values: + lines.append(f" {value.c_name} = {value.value},") + lines.append(f"}} {enum_model.c_name};") + lines.append("") + lines.extend( + [ + "const char* ifcopenshell_last_error_message(void);", + "void ifcopenshell_last_error_clear(void);", + "void ifcopenshell_string_free(char* value);", + "", + ] + ) + for variant in _all_variants(model): + return_type = _return_c_type(variant.callable.return_adapter, model) + parameters = ", ".join( + f"{_parameter_c_type(parameter, model)} {parameter.name}" + for parameter in variant.parameters + ) + if variant.callable.kind == "method": + self_type = f"{_class_c_type(variant.owner, model)}* handle" + parameters = f"{self_type}, {parameters}" if parameters else self_type + lines.append(f"{return_type} {model.c_prefix}_{variant.api_name}({parameters});") + if _all_variants(model): + lines.append("") + for class_model in sequence_targets: + list_prefix = f"{model.c_prefix}_{_class_c_identifier(class_model, model)}_list" + lines.append(f"int {list_prefix}_size(const {_list_c_type(class_model, model)}* handle);") + lines.append(f"{_class_c_type(class_model, model)}* {list_prefix}_get(const {_list_c_type(class_model, model)}* handle, int index);") + lines.append(f"void {list_prefix}_free({_list_c_type(class_model, model)}* handle);") + lines.append("") + for class_model in model.classes: + lines.append(f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle);") + lines.extend( + [ + "", + "#ifdef __cplusplus", + "}", + "#endif", + "", + "#endif", + "", + ] + ) + return "\n".join(lines) + + +def emit_c_api_implementation(model: ModuleModel) -> str: + sequence_targets = _sequence_targets(model) + lines = [ + f'#include "{model.api_header_name}"', + "", + ] + for header in sorted(dict.fromkeys(model.source_headers)): + lines.append(f'#include "{header}"') + lines.extend( + [ + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "namespace {", + "thread_local std::string g_last_error;", + "", + "char* duplicate_string(const std::string& value) {", + " auto* buffer = new char[value.size() + 1];", + " std::copy(value.begin(), value.end(), buffer);", + " buffer[value.size()] = '\\0';", + " return buffer;", + "}", + "", + "void set_last_error(const std::exception& exception) {", + " g_last_error = exception.what();", + "}", + "}", + "", + ] + ) + for class_model in model.classes: + lines.append(f"struct {_class_c_type(class_model, model)} {{") + if class_model.owner_cpp_name is not None: + lines.append(f" std::shared_ptr<{class_model.owner_cpp_name}> owner;") + if class_model.handle_kind == "shared_ptr": + lines.append(f" std::shared_ptr<{class_model.cpp_name}> value;") + else: + lines.append(f" {class_model.cpp_name} value;") + lines.append("};") + lines.append("") + for class_model in sequence_targets: + lines.append(f"struct {_list_c_type(class_model, model)} {{") + if class_model.owner_cpp_name is not None: + lines.append(f" std::shared_ptr<{class_model.owner_cpp_name}> owner;") + lines.append(f" std::vector<{class_model.cpp_name}> value;") + lines.append("};") + lines.append("") + lines.extend( + [ + 'extern "C" {', + "", + "const char* ifcopenshell_last_error_message(void) {", + " return g_last_error.empty() ? nullptr : g_last_error.c_str();", + "}", + "", + "void ifcopenshell_last_error_clear(void) {", + " g_last_error.clear();", + "}", + "", + "void ifcopenshell_string_free(char* value) {", + " delete[] value;", + "}", + "", + ] + ) + for variant in _all_variants(model): + return_type = _return_c_type(variant.callable.return_adapter, model) + parameter_list = ", ".join( + f"{_parameter_c_type(parameter, model)} {parameter.name}" + for parameter in variant.parameters + ) + if variant.callable.kind == "method": + self_type = f"{_class_c_type(variant.owner, model)}* handle" + parameter_list = f"{self_type}, {parameter_list}" if parameter_list else self_type + lines.append(f"{return_type} {model.c_prefix}_{variant.api_name}({parameter_list}) {{") + lines.append(" ifcopenshell_last_error_clear();") + lines.append(" try {") + if variant.callable.kind == "method": + lines.append(" if (handle == nullptr) {") + lines.append(' throw std::runtime_error("Null handle received");') + lines.append(" }") + for parameter in variant.parameters: + if is_handle_adapter(parameter.adapter): + lines.append(f" if ({parameter.name} == nullptr) {{") + lines.append(f' throw std::runtime_error("Null handle parameter received for {parameter.name}");') + lines.append(" }") + call_expression = _call_expression(variant, model) + if variant.callable.kind == "constructor": + lines.append(f" auto constructed_value = {call_expression};") + if variant.owner.handle_kind == "shared_ptr": + lines.append(f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};") + elif variant.owner.owner_cpp_name is not None: + lines.append(f" return new {_class_c_type(variant.owner, model)}{{ {{}}, std::move(constructed_value) }};") + else: + lines.append(f" return new {_class_c_type(variant.owner, model)}{{ std::move(constructed_value) }};") + elif variant.callable.return_adapter == "string": + lines.append(f" auto result = {call_expression};") + lines.append(" return duplicate_string(result);") + elif variant.callable.return_adapter in {"integer", "bool", "void"} or is_enum_adapter(variant.callable.return_adapter): + if variant.callable.return_adapter == "void": + lines.append(f" {call_expression};") + lines.append(" return;") + else: + lines.append(f" return {call_expression};") + elif is_handle_adapter(variant.callable.return_adapter): + target = _class_index(model)[handle_adapter_target(variant.callable.return_adapter)] + _emit_handle_return_lines(lines, variant.owner, target, variant.callable, call_expression, model) + elif is_sequence_adapter(variant.callable.return_adapter): + target = _class_index(model)[sequence_adapter_target(variant.callable.return_adapter)] + _emit_sequence_return_lines(lines, variant.owner, target, variant.callable, call_expression, model) + else: + raise RuntimeError(f"Unsupported return adapter in C API emitter: {variant.callable.return_adapter}") + lines.append(" } catch (const std::exception& exception) {") + lines.append(" set_last_error(exception);") + if return_type == "void": + lines.append(" return;") + elif return_type in {"int", "bool"} or is_enum_adapter(variant.callable.return_adapter): + lines.append(" return 0;") + else: + lines.append(" return nullptr;") + lines.append(" }") + lines.append("}") + lines.append("") + for class_model in sequence_targets: + list_prefix = f"{model.c_prefix}_{_class_c_identifier(class_model, model)}_list" + lines.extend( + [ + f"int {list_prefix}_size(const {_list_c_type(class_model, model)}* handle) {{", + " ifcopenshell_last_error_clear();", + " try {", + " if (handle == nullptr) {", + ' throw std::runtime_error("Null list handle received");', + " }", + " return static_cast(handle->value.size());", + " } catch (const std::exception& exception) {", + " set_last_error(exception);", + " return 0;", + " }", + "}", + "", + f"{_class_c_type(class_model, model)}* {list_prefix}_get(const {_list_c_type(class_model, model)}* handle, int index) {{", + " ifcopenshell_last_error_clear();", + " try {", + " if (handle == nullptr) {", + ' throw std::runtime_error("Null list handle received");', + " }", + " if (index < 0 || static_cast(index) >= handle->value.size()) {", + ' throw std::out_of_range("List index out of range");', + " }", + ] + ) + if class_model.handle_kind == "shared_ptr": + lines.append(f" auto item_value = std::make_shared<{class_model.cpp_name}>(handle->value.at(static_cast(index)));") + lines.append(f" return new {_class_c_type(class_model, model)}{{ std::move(item_value) }};") + elif class_model.owner_cpp_name is not None: + lines.append(f" auto item_value = handle->value.at(static_cast(index));") + lines.append(f" return new {_class_c_type(class_model, model)}{{ handle->owner, std::move(item_value) }};") + else: + lines.append(f" auto item_value = handle->value.at(static_cast(index));") + lines.append(f" return new {_class_c_type(class_model, model)}{{ std::move(item_value) }};") + lines.extend( + [ + " } catch (const std::exception& exception) {", + " set_last_error(exception);", + " return nullptr;", + " }", + "}", + "", + f"void {list_prefix}_free({_list_c_type(class_model, model)}* handle) {{", + " delete handle;", + "}", + "", + ] + ) + for class_model in model.classes: + lines.append(f"void {model.c_prefix}_{_class_c_identifier(class_model, model)}_free({_class_c_type(class_model, model)}* handle) {{") + lines.append(" delete handle;") + lines.append("}") + lines.append("") + lines.extend(["}", ""]) + return "\n".join(lines) + + +def emit_python_extension(model: ModuleModel) -> str: + class_models = _class_index(model) + lines = [ + "#define PY_SSIZE_T_CLEAN", + "#include ", + "", + f'#include "{model.api_header_name}"', + "", + ] + for class_model in model.classes: + lines.append( + f'static const char* {_capsule_name_symbol(class_model)} = "{model.module_name}.{_class_c_identifier(class_model, model)}";' + ) + lines.extend( + [ + "", + "static PyObject* raise_last_error(const char* fallback_message) {", + " const char* message = ifcopenshell_last_error_message();", + " PyErr_SetString(PyExc_RuntimeError, message ? message : fallback_message);", + " return nullptr;", + "}", + "", + ] + ) + for class_model in model.classes: + lines.extend( + [ + f"static void {_capsule_destructor_name(class_model)}(PyObject* capsule) {{", + f" auto* handle = static_cast<{_class_c_type(class_model, model)}*>(PyCapsule_GetPointer(capsule, {_capsule_name_symbol(class_model)}));", + " if (handle != nullptr) {", + f" {model.c_prefix}_{_class_c_identifier(class_model, model)}_free(handle);", + " }", + " PyErr_Clear();", + "}", + "", + ] + ) + for variant in _all_variants(model): + lines.append(f"static PyObject* py_{variant.api_name}(PyObject*, PyObject* args) {{") + parse_format: list[str] = [] + parse_targets: list[str] = [] + call_arguments: list[str] = [] + if variant.callable.kind == "method": + lines.append(" PyObject* self_capsule = nullptr;") + lines.append(f" auto* handle = static_cast<{_class_c_type(variant.owner, model)}*>(nullptr);") + parse_format.append("O") + parse_targets.append("&self_capsule") + for parameter in variant.parameters: + if parameter.adapter == "string": + lines.append(f" const char* {parameter.name} = nullptr;") + parse_format.append("s") + parse_targets.append(f"&{parameter.name}") + elif parameter.adapter == "bool": + lines.append(f" int {parameter.name} = 0;") + parse_format.append("p") + parse_targets.append(f"&{parameter.name}") + elif parameter.adapter == "integer" or is_enum_adapter(parameter.adapter): + lines.append(f" int {parameter.name} = 0;") + parse_format.append("i") + parse_targets.append(f"&{parameter.name}") + elif is_handle_adapter(parameter.adapter): + target = class_models[handle_adapter_target(parameter.adapter)] + lines.append(f" PyObject* {parameter.name}_capsule = nullptr;") + lines.append(f" auto* {parameter.name} = static_cast<{_class_c_type(target, model)}*>(nullptr);") + parse_format.append("O") + parse_targets.append(f"&{parameter.name}_capsule") + else: + raise RuntimeError(f"Unsupported parameter adapter in Python extension emitter: {parameter.adapter}") + if parse_targets: + lines.append(f' if (!PyArg_ParseTuple(args, "{"".join(parse_format)}", {", ".join(parse_targets)})) {{') + else: + lines.append(' if (!PyArg_ParseTuple(args, "")) {') + lines.append(" return nullptr;") + lines.append(" }") + if variant.callable.kind == "method": + lines.append( + f" handle = static_cast<{_class_c_type(variant.owner, model)}*>(PyCapsule_GetPointer(self_capsule, {_capsule_name_symbol(variant.owner)}));" + ) + lines.append(" if (handle == nullptr) {") + lines.append(" return nullptr;") + lines.append(" }") + call_arguments.append("handle") + for parameter in variant.parameters: + if is_handle_adapter(parameter.adapter): + target = class_models[handle_adapter_target(parameter.adapter)] + lines.append( + f" {parameter.name} = static_cast<{_class_c_type(target, model)}*>(PyCapsule_GetPointer({parameter.name}_capsule, {_capsule_name_symbol(target)}));" + ) + lines.append(f" if ({parameter.name} == nullptr) {{") + lines.append(" return nullptr;") + lines.append(" }") + call_arguments.append(_extension_native_argument(parameter, model)) + native_call = f"{model.c_prefix}_{variant.api_name}({', '.join(call_arguments)})" + if variant.callable.return_adapter == "string": + lines.append(f" char* result = {native_call};") + lines.append(" if (result == nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" PyObject* value = PyUnicode_FromString(result);") + lines.append(" ifcopenshell_string_free(result);") + lines.append(" return value;") + elif variant.callable.return_adapter == "integer": + lines.append(f" int result = {native_call};") + lines.append(" if (ifcopenshell_last_error_message() != nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" return PyLong_FromLong(result);") + elif variant.callable.return_adapter == "bool": + lines.append(f" bool result = {native_call};") + lines.append(" if (ifcopenshell_last_error_message() != nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" return PyBool_FromLong(result ? 1 : 0);") + elif variant.callable.return_adapter == "void": + lines.append(f" {native_call};") + lines.append(" if (ifcopenshell_last_error_message() != nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" Py_RETURN_NONE;") + elif is_enum_adapter(variant.callable.return_adapter): + lines.append(f" int result = {native_call};") + lines.append(" if (ifcopenshell_last_error_message() != nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" return PyLong_FromLong(result);") + elif is_handle_adapter(variant.callable.return_adapter): + target = class_models[handle_adapter_target(variant.callable.return_adapter)] + lines.append(f" auto* result = {native_call};") + lines.append(" if (result == nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append( + f" return PyCapsule_New(result, {_capsule_name_symbol(target)}, {_capsule_destructor_name(target)});" + ) + elif is_sequence_adapter(variant.callable.return_adapter): + target = class_models[sequence_adapter_target(variant.callable.return_adapter)] + list_prefix = f"{model.c_prefix}_{_class_c_identifier(target, model)}_list" + lines.append(f" auto* result = {native_call};") + lines.append(" if (result == nullptr) {") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(f" int size = {list_prefix}_size(result);") + lines.append(" if (ifcopenshell_last_error_message() != nullptr) {") + lines.append(f" {list_prefix}_free(result);") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append(" PyObject* values = PyList_New(size);") + lines.append(" if (values == nullptr) {") + lines.append(f" {list_prefix}_free(result);") + lines.append(" return nullptr;") + lines.append(" }") + lines.append(" for (int index = 0; index < size; ++index) {") + lines.append(f" auto* item = {list_prefix}_get(result, index);") + lines.append(" if (item == nullptr) {") + lines.append(" Py_DECREF(values);") + lines.append(f" {list_prefix}_free(result);") + lines.append(' return raise_last_error("Native call failed");') + lines.append(" }") + lines.append( + f" PyObject* capsule = PyCapsule_New(item, {_capsule_name_symbol(target)}, {_capsule_destructor_name(target)});" + ) + lines.append(" if (capsule == nullptr) {") + lines.append(f" {model.c_prefix}_{_class_c_identifier(target, model)}_free(item);") + lines.append(" Py_DECREF(values);") + lines.append(f" {list_prefix}_free(result);") + lines.append(" return nullptr;") + lines.append(" }") + lines.append(" PyList_SET_ITEM(values, index, capsule);") + lines.append(" }") + lines.append(f" {list_prefix}_free(result);") + lines.append(" return values;") + else: + raise RuntimeError(f"Unsupported return adapter in Python extension emitter: {variant.callable.return_adapter}") + lines.append("}") + lines.append("") + lines.extend(["static PyMethodDef MODULE_METHODS[] = {"]) + for variant in _all_variants(model): + lines.append(f' {{"{variant.api_name}", py_{variant.api_name}, METH_VARARGS, nullptr}},') + lines.extend( + [ + " {nullptr, nullptr, 0, nullptr},", + "};", + "", + "static PyModuleDef MODULE_DEF = {", + " PyModuleDef_HEAD_INIT,", + f' "_{model.module_name}",', + " nullptr,", + " -1,", + " MODULE_METHODS,", + "};", + "", + f"PyMODINIT_FUNC PyInit__{model.module_name}(void) {{", + " PyObject* module = PyModule_Create(&MODULE_DEF);", + " if (module == nullptr) {", + " return nullptr;", + " }", + ] + ) + for enum_model in model.enums: + for value in enum_model.values: + lines.append(f' if (PyModule_AddIntConstant(module, "{value.name}", {value.c_name}) < 0) {{') + lines.append(" Py_DECREF(module);") + lines.append(" return nullptr;") + lines.append(" }") + lines.extend([" return module;", "}", ""]) + return "\n".join(lines) + + +def _python_type_for_parameter(parameter: ParameterModel, model: ModuleModel) -> str: + if parameter.adapter == "string": + return "str" + if parameter.adapter == "integer": + return "int" + if parameter.adapter == "bool": + return "bool" + if is_enum_adapter(parameter.adapter): + return _enum_index(model)[enum_adapter_target(parameter.adapter)].py_name + if is_handle_adapter(parameter.adapter): + return _class_index(model)[handle_adapter_target(parameter.adapter)].py_name + return "object" + + +def _python_type_for_return(adapter: str, model: ModuleModel) -> str: + if adapter == "string": + return "str" + if adapter == "integer": + return "int" + if adapter == "bool": + return "bool" + if adapter == "void": + return "None" + if is_enum_adapter(adapter): + return _enum_index(model)[enum_adapter_target(adapter)].py_name + if is_handle_adapter(adapter): + return _class_index(model)[handle_adapter_target(adapter)].py_name + if is_sequence_adapter(adapter): + target = _class_index(model)[sequence_adapter_target(adapter)] + return f"list[{target.py_name}]" + return "object" + + +def _python_parameter_signature(parameter: ParameterModel, model: ModuleModel) -> str: + signature = f"{parameter.name}: {_python_type_for_parameter(parameter, model)}" + if parameter.default_python_value is not None: + signature += f" = {parameter.default_python_value}" + return signature + + +def _python_native_argument(parameter: ParameterModel) -> str: + if is_enum_adapter(parameter.adapter): + return f"int({parameter.name})" + if is_handle_adapter(parameter.adapter): + return f"{parameter.name}._handle" + return parameter.name + + +def _extension_native_argument(parameter: ParameterModel, model: ModuleModel) -> str: + if is_enum_adapter(parameter.adapter): + return f"static_cast<{_enum_c_type(parameter.adapter, model)}>({parameter.name})" + return parameter.name + + +def _emit_python_return( + lines: list[str], + call_expression: str, + adapter: str, + model: ModuleModel, + indent: str, +) -> None: + if adapter in {"string", "integer", "bool"}: + lines.append(f"{indent}return {call_expression}") + return + if adapter == "void": + lines.append(f"{indent}{call_expression}") + lines.append(f"{indent}return None") + return + if is_enum_adapter(adapter): + enum_model = _enum_index(model)[enum_adapter_target(adapter)] + lines.append(f"{indent}return {enum_model.py_name}({call_expression})") + return + if is_handle_adapter(adapter): + target = _class_index(model)[handle_adapter_target(adapter)] + lines.append(f"{indent}return {target.py_name}({call_expression})") + return + if is_sequence_adapter(adapter): + target = _class_index(model)[sequence_adapter_target(adapter)] + lines.append(f"{indent}return [{target.py_name}(item) for item in {call_expression}]") + return + raise RuntimeError(f"Unsupported return adapter in Python facade emitter: {adapter}") + + +def emit_python_facade(model: ModuleModel) -> str: + lines = [ + "from __future__ import annotations", + "", + "from enum import IntEnum", + "", + f"import _{model.module_name} as _native", + "", + ] + for enum_model in model.enums: + lines.append(f"class {enum_model.py_name}(IntEnum):") + for value in enum_model.values: + lines.append(f" {value.name} = _native.{value.name}") + lines.append("") + for class_model in model.classes: + lines.append(f"class {class_model.py_name}:") + lines.append(' __slots__ = ("_handle",)') + lines.append("") + lines.append(" def __init__(self, handle) -> None:") + lines.append(" self._handle = handle") + lines.append("") + for callable_model in class_model.callables: + parameters = ", ".join(_python_parameter_signature(parameter, model) for parameter in callable_model.parameters) + full_variant = _full_variant(class_model, callable_model) + call_arguments = ", ".join(_python_native_argument(parameter) for parameter in callable_model.parameters) + return_annotation = _python_type_for_return(callable_model.return_adapter, model) + if callable_model.kind == "constructor": + lines.append(" @staticmethod") + lines.append(f" def {callable_model.py_name}({parameters}) -> {class_model.py_name}:") + native_call = f"_native.{full_variant.api_name}({call_arguments})" + _emit_python_return(lines, native_call, callable_model.return_adapter, model, " ") + else: + signature = f"self, {parameters}" if parameters else "self" + separator = ", " if call_arguments else "" + native_call = f"_native.{full_variant.api_name}(self._handle{separator}{call_arguments})" + lines.append(f" def {callable_model.py_name}({signature}) -> {return_annotation}:") + _emit_python_return(lines, native_call, callable_model.return_adapter, model, " ") + lines.append("") + if not class_model.callables: + lines.append(" pass") + lines.append("") + return "\n".join(lines) + + +def write_module_outputs(model: ModuleModel, output_dir: Path) -> None: + output_dir.mkdir(parents=True, exist_ok=True) + (output_dir / model.api_header_name).write_text(emit_c_api_header(model), encoding="utf-8") + (output_dir / model.api_implementation_name).write_text(emit_c_api_implementation(model), encoding="utf-8") + (output_dir / model.extension_source_name).write_text(emit_python_extension(model), encoding="utf-8") + (output_dir / model.python_source_name).write_text(emit_python_facade(model), encoding="utf-8") diff --git a/src/wrappergen/examples/print_walls.py b/src/wrappergen/examples/print_walls.py new file mode 100644 index 0000000000..6d4c14f416 --- /dev/null +++ b/src/wrappergen/examples/print_walls.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import sys +from pathlib import Path + + +def main() -> int: + if len(sys.argv) != 2: + print("Usage: python print_walls.py path/to/model.ifc") + return 1 + + generated_dir = Path(__file__).resolve().parents[1] / "generated" + if str(generated_dir) not in sys.path: + sys.path.insert(0, str(generated_dir)) + + import ifcopenshell_experimental as ifx + + model = ifx.file.with_path(sys.argv[1]) + for wall in model.instances_by_type("IfcWall"): + print(f"#{wall.id()} {wall.declaration().name()}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/wrappergen/generate.py b/src/wrappergen/generate.py new file mode 100644 index 0000000000..46ee6346bb --- /dev/null +++ b/src/wrappergen/generate.py @@ -0,0 +1,134 @@ +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +if __package__ in {None, ""}: + sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + from wrappergen.clang_frontend import build_module_model + from wrappergen.config import CompilationConfig, IgnoreConfig, WrapperConfig + from wrappergen.emit import write_module_outputs +else: + from .clang_frontend import build_module_model + from .config import CompilationConfig, IgnoreConfig, WrapperConfig + from .emit import write_module_outputs + + +def _existing_directories(paths: list[Path]) -> list[str]: + seen: set[str] = set() + results: list[str] = [] + for path in paths: + resolved = str(path.resolve()) + if path.is_dir() and resolved not in seen: + seen.add(resolved) + results.append(resolved) + return results + + +def _discover_headers(src_ifcparse: Path) -> list[str]: + return [ + str(path.resolve()) + for path in sorted(src_ifcparse.glob("*.h")) + if path.parent.name != "schemas" + ] + + +def _discover_boost_include_dirs() -> list[Path]: + candidates: list[Path] = [] + prefix = Path(sys.prefix) + candidates.extend( + [ + prefix / "Library" / "include", + prefix / "include", + ] + ) + + executable = Path(sys.executable).resolve() + conda_root = executable.parents[2] if len(executable.parents) >= 3 else None + if conda_root is None: + return candidates + + pkgs = conda_root / "pkgs" + if not pkgs.is_dir(): + return candidates + + for pattern in ("libboost-headers-*", "boost-cpp-*"): + for package_dir in sorted(pkgs.glob(pattern), reverse=True): + include_dir = package_dir / "Library" / "include" + if (include_dir / "boost" / "lexical_cast.hpp").is_file(): + candidates.append(include_dir) + return candidates + + +def build_default_wrapper_config(repo_root: Path) -> WrapperConfig: + src_ifcparse = repo_root / "src" / "ifcparse" + include_dirs = _existing_directories([src_ifcparse, *_discover_boost_include_dirs()]) + return WrapperConfig( + module_name="ifcopenshell_experimental", + c_prefix="ifcopenshell", + api_header_name="ifcopenshell_experimental_c_api.h", + api_implementation_name="ifcopenshell_experimental_c_api.cpp", + extension_source_name="_ifcopenshell_experimental.cpp", + python_source_name="ifcopenshell_experimental.py", + allowed_namespaces=["ifcopenshell", "express"], + enum_names={"ifcopenshell::filetype": "FileType"}, + parameter_names={"type": "filetype", "read_only": "readonly"}, + class_handle_kinds={"ifcopenshell::file": "shared_ptr"}, + class_owner_types={ + "express::Base": "ifcopenshell::file", + "express::Entity": "ifcopenshell::file", + "express::Select": "ifcopenshell::file", + "express::DeclaredType": "ifcopenshell::file", + }, + type_adapters={ + "std::string": "string", + "int": "integer", + "size_t": "integer", + "std::size_t": "integer", + "unsigned int": "integer", + "uint32_t": "integer", + "bool": "bool", + "void": "void", + }, + ignore=IgnoreConfig( + namespaces=["ifcopenshell::impl"], + classes=[], + enums=[], + methods=[], + ), + compilation=CompilationConfig( + headers=_discover_headers(src_ifcparse), + include_dirs=include_dirs, + ), + ) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Generate an experimental C API, CPython module, and Python facade for ifcparse." + ) + parser.add_argument( + "--repo-root", + default=str(Path(__file__).resolve().parents[2]), + help="Repository root that contains src/ifcparse", + ) + parser.add_argument( + "--output-dir", + default=str(Path(__file__).resolve().parent / "generated"), + help="Directory that will receive the generated files", + ) + return parser.parse_args() + + +def main() -> int: + arguments = parse_args() + repo_root = Path(arguments.repo_root).resolve() + output_dir = Path(arguments.output_dir).resolve() + model = build_module_model(build_default_wrapper_config(repo_root)) + write_module_outputs(model, output_dir) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/wrappergen/generated/_ifcopenshell_experimental.cpp b/src/wrappergen/generated/_ifcopenshell_experimental.cpp new file mode 100644 index 0000000000..2600c244ca --- /dev/null +++ b/src/wrappergen/generated/_ifcopenshell_experimental.cpp @@ -0,0 +1,2616 @@ +#define PY_SSIZE_T_CLEAN +#include + +#include "ifcopenshell_experimental_c_api.h" + +static const char* IFCOPENSHELL_EXCEPTION_CAPSULE_NAME = "ifcopenshell_experimental.exception"; +static const char* IFCOPENSHELL_ATTRIBUTE_OUT_OF_RANGE_EXCEPTION_CAPSULE_NAME = "ifcopenshell_experimental.attribute_out_of_range_exception"; +static const char* IFCOPENSHELL_INVALID_TOKEN_EXCEPTION_CAPSULE_NAME = "ifcopenshell_experimental.invalid_token_exception"; +static const char* IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.parameter_type"; +static const char* IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.named_type"; +static const char* IFCOPENSHELL_SIMPLE_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.simple_type"; +static const char* IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.aggregation_type"; +static const char* IFCOPENSHELL_DECLARATION_CAPSULE_NAME = "ifcopenshell_experimental.declaration"; +static const char* IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME = "ifcopenshell_experimental.type_declaration"; +static const char* IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.select_type"; +static const char* IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.enumeration_type"; +static const char* IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME = "ifcopenshell_experimental.attribute"; +static const char* IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME = "ifcopenshell_experimental.inverse_attribute"; +static const char* IFCOPENSHELL_ENTITY_CAPSULE_NAME = "ifcopenshell_experimental.entity"; +static const char* IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME = "ifcopenshell_experimental.schema_definition"; +static const char* EXPRESS_BASE_CAPSULE_NAME = "ifcopenshell_experimental.express_base"; +static const char* EXPRESS_ENTITY_CAPSULE_NAME = "ifcopenshell_experimental.express_entity"; +static const char* EXPRESS_SELECT_CAPSULE_NAME = "ifcopenshell_experimental.express_select"; +static const char* EXPRESS_DECLARED_TYPE_CAPSULE_NAME = "ifcopenshell_experimental.express_declared_type"; +static const char* IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME = "ifcopenshell_experimental.full_buffer_impl"; +static const char* IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME = "ifcopenshell_experimental.paged_file_impl"; +static const char* IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME = "ifcopenshell_experimental.pushed_sequential_impl"; +static const char* IFCOPENSHELL_CHARACTER_ENCODER_CAPSULE_NAME = "ifcopenshell_experimental.character_encoder"; +static const char* IFCOPENSHELL_FILE_OPEN_STATUS_CAPSULE_NAME = "ifcopenshell_experimental.file_open_status"; +static const char* IFCOPENSHELL_SPF_HEADER_CAPSULE_NAME = "ifcopenshell_experimental.spf_header"; +static const char* IFCOPENSHELL_FILE_CAPSULE_NAME = "ifcopenshell_experimental.file"; +static const char* IFCOPENSHELL_GLOBAL_ID_CAPSULE_NAME = "ifcopenshell_experimental.global_id"; + +static PyObject* raise_last_error(const char* fallback_message) { + const char* message = ifcopenshell_last_error_message(); + PyErr_SetString(PyExc_RuntimeError, message ? message : fallback_message); + return nullptr; +} + +static void ifcopenshell_exception_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_EXCEPTION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_exception_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_attribute_out_of_range_exception_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_ATTRIBUTE_OUT_OF_RANGE_EXCEPTION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_attribute_out_of_range_exception_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_invalid_token_exception_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_INVALID_TOKEN_EXCEPTION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_invalid_token_exception_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_parameter_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_parameter_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_named_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_named_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_simple_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_SIMPLE_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_simple_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_aggregation_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_aggregation_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_declaration_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_declaration_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_type_declaration_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_type_declaration_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_select_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_select_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_enumeration_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_enumeration_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_attribute_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_attribute_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_inverse_attribute_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_inverse_attribute_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_entity_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_entity_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_schema_definition_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_schema_definition_free(handle); + } + PyErr_Clear(); +} + +static void express_base_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, EXPRESS_BASE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_express_base_free(handle); + } + PyErr_Clear(); +} + +static void express_entity_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, EXPRESS_ENTITY_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_express_entity_free(handle); + } + PyErr_Clear(); +} + +static void express_select_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, EXPRESS_SELECT_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_express_select_free(handle); + } + PyErr_Clear(); +} + +static void express_declared_type_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, EXPRESS_DECLARED_TYPE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_express_declared_type_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_full_buffer_impl_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_full_buffer_impl_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_paged_file_impl_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_paged_file_impl_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_pushed_sequential_impl_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_pushed_sequential_impl_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_character_encoder_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_CHARACTER_ENCODER_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_character_encoder_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_file_open_status_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_FILE_OPEN_STATUS_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_file_open_status_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_spf_header_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_SPF_HEADER_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_spf_header_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_file_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_file_free(handle); + } + PyErr_Clear(); +} + +static void ifcopenshell_global_id_capsule_destructor(PyObject* capsule) { + auto* handle = static_cast(PyCapsule_GetPointer(capsule, IFCOPENSHELL_GLOBAL_ID_CAPSULE_NAME)); + if (handle != nullptr) { + ifcopenshell_global_id_free(handle); + } + PyErr_Clear(); +} + +static PyObject* py_exception_new_with_message(PyObject*, PyObject* args) { + const char* message = nullptr; + if (!PyArg_ParseTuple(args, "s", &message)) { + return nullptr; + } + auto* result = ifcopenshell_exception_new_with_message(message); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_EXCEPTION_CAPSULE_NAME, ifcopenshell_exception_capsule_destructor); +} + +static PyObject* py_attribute_out_of_range_exception_new_with_message(PyObject*, PyObject* args) { + const char* message = nullptr; + if (!PyArg_ParseTuple(args, "s", &message)) { + return nullptr; + } + auto* result = ifcopenshell_attribute_out_of_range_exception_new_with_message(message); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ATTRIBUTE_OUT_OF_RANGE_EXCEPTION_CAPSULE_NAME, ifcopenshell_attribute_out_of_range_exception_capsule_destructor); +} + +static PyObject* py_invalid_token_exception_new_with_token_start_token_string_expected_type(PyObject*, PyObject* args) { + int token_start = 0; + const char* token_string = nullptr; + const char* expected_type = nullptr; + if (!PyArg_ParseTuple(args, "iss", &token_start, &token_string, &expected_type)) { + return nullptr; + } + auto* result = ifcopenshell_invalid_token_exception_new_with_token_start_token_string_expected_type(token_start, token_string, expected_type); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_INVALID_TOKEN_EXCEPTION_CAPSULE_NAME, ifcopenshell_invalid_token_exception_capsule_destructor); +} + +static PyObject* py_parameter_type_as_named_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_parameter_type_as_named_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME, ifcopenshell_named_type_capsule_destructor); +} + +static PyObject* py_parameter_type_as_simple_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_parameter_type_as_simple_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SIMPLE_TYPE_CAPSULE_NAME, ifcopenshell_simple_type_capsule_destructor); +} + +static PyObject* py_parameter_type_as_aggregation_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_parameter_type_as_aggregation_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME, ifcopenshell_aggregation_type_capsule_destructor); +} + +static PyObject* py_parameter_type_is(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* arg0 = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &arg0)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_parameter_type_is(handle, arg0); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_named_type_declared_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_named_type_declared_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_named_type_as_named_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_named_type_as_named_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME, ifcopenshell_named_type_capsule_destructor); +} + +static PyObject* py_named_type_is(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_NAMED_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_named_type_is(handle, name); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_simple_type_as_simple_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SIMPLE_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_simple_type_as_simple_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SIMPLE_TYPE_CAPSULE_NAME, ifcopenshell_simple_type_capsule_destructor); +} + +static PyObject* py_aggregation_type_bound1(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_aggregation_type_bound1(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_aggregation_type_bound2(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_aggregation_type_bound2(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_aggregation_type_type_of_element(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_aggregation_type_type_of_element(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME, ifcopenshell_parameter_type_capsule_destructor); +} + +static PyObject* py_aggregation_type_as_aggregation_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_aggregation_type_as_aggregation_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_AGGREGATION_TYPE_CAPSULE_NAME, ifcopenshell_aggregation_type_capsule_destructor); +} + +static PyObject* py_declaration_new_with_name_index_in_schema(PyObject*, PyObject* args) { + const char* name = nullptr; + int index_in_schema = 0; + if (!PyArg_ParseTuple(args, "si", &name, &index_in_schema)) { + return nullptr; + } + auto* result = ifcopenshell_declaration_new_with_name_index_in_schema(name, index_in_schema); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_declaration_name(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_declaration_name(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyObject* py_declaration_name_uc(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_declaration_name_uc(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyObject* py_declaration_as_type_declaration(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_declaration_as_type_declaration(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME, ifcopenshell_type_declaration_capsule_destructor); +} + +static PyObject* py_declaration_as_select_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_declaration_as_select_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME, ifcopenshell_select_type_capsule_destructor); +} + +static PyObject* py_declaration_as_enumeration_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_declaration_as_enumeration_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME, ifcopenshell_enumeration_type_capsule_destructor); +} + +static PyObject* py_declaration_as_entity(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_declaration_as_entity(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); +} + +static PyObject* py_declaration_is(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_declaration_is(handle, name); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_declaration_index_in_schema(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_declaration_index_in_schema(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_declaration_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_declaration_type(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_declaration_schema(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_declaration_schema(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME, ifcopenshell_schema_definition_capsule_destructor); +} + +static PyObject* py_type_declaration_declared_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_type_declaration_declared_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME, ifcopenshell_parameter_type_capsule_destructor); +} + +static PyObject* py_type_declaration_as_type_declaration(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_type_declaration_as_type_declaration(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME, ifcopenshell_type_declaration_capsule_destructor); +} + +static PyObject* py_select_type_select_list(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_select_type_select_list(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_declaration_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_declaration_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_declaration_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_declaration_free(item); + Py_DECREF(values); + ifcopenshell_declaration_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_declaration_list_free(result); + return values; +} + +static PyObject* py_select_type_as_select_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_select_type_as_select_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME, ifcopenshell_select_type_capsule_destructor); +} + +static PyObject* py_enumeration_type_lookup_enum_offset(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* value_name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &value_name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_enumeration_type_lookup_enum_offset(handle, value_name); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_enumeration_type_as_enumeration_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_enumeration_type_as_enumeration_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME, ifcopenshell_enumeration_type_capsule_destructor); +} + +static PyObject* py_attribute_name(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_attribute_name(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyObject* py_attribute_type_of_attribute(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_attribute_type_of_attribute(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_PARAMETER_TYPE_CAPSULE_NAME, ifcopenshell_parameter_type_capsule_destructor); +} + +static PyObject* py_attribute_optional(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_attribute_optional(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_inverse_attribute_name(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_inverse_attribute_name(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyObject* py_inverse_attribute_bound1(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_inverse_attribute_bound1(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_inverse_attribute_bound2(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_inverse_attribute_bound2(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_inverse_attribute_entity_reference(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_inverse_attribute_entity_reference(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); +} + +static PyObject* py_inverse_attribute_attribute_reference(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_inverse_attribute_attribute_reference(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME, ifcopenshell_attribute_capsule_destructor); +} + +static PyObject* py_entity_is_abstract(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_entity_is_abstract(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_entity_subtypes(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_subtypes(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_entity_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_entity_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_entity_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_entity_free(item); + Py_DECREF(values); + ifcopenshell_entity_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_entity_list_free(result); + return values; +} + +static PyObject* py_entity_attributes(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_attributes(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_attribute_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_attribute_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_attribute_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME, ifcopenshell_attribute_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_attribute_free(item); + Py_DECREF(values); + ifcopenshell_attribute_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_attribute_list_free(result); + return values; +} + +static PyObject* py_entity_all_attributes(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_all_attributes(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_attribute_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_attribute_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_attribute_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME, ifcopenshell_attribute_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_attribute_free(item); + Py_DECREF(values); + ifcopenshell_attribute_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_attribute_list_free(result); + return values; +} + +static PyObject* py_entity_all_inverse_attributes(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_all_inverse_attributes(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_inverse_attribute_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_inverse_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_inverse_attribute_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_inverse_attribute_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_inverse_attribute_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_INVERSE_ATTRIBUTE_CAPSULE_NAME, ifcopenshell_inverse_attribute_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_inverse_attribute_free(item); + Py_DECREF(values); + ifcopenshell_inverse_attribute_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_inverse_attribute_list_free(result); + return values; +} + +static PyObject* py_entity_attribute_by_index(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int index = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &index)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_attribute_by_index(handle, index); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ATTRIBUTE_CAPSULE_NAME, ifcopenshell_attribute_capsule_destructor); +} + +static PyObject* py_entity_attribute_count(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_entity_attribute_count(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_entity_supertype(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_supertype(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); +} + +static PyObject* py_entity_as_entity(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_as_entity(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); +} + +static PyObject* py_schema_definition_declaration_by_name_with_name(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_declaration_by_name_with_name(handle, name); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_schema_definition_declaration_by_name_with_declaration_index(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int declaration_index = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &declaration_index)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_declaration_by_name_with_declaration_index(handle, declaration_index); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_schema_definition_declarations(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_declarations(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_declaration_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_declaration_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_declaration_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_declaration_free(item); + Py_DECREF(values); + ifcopenshell_declaration_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_declaration_list_free(result); + return values; +} + +static PyObject* py_schema_definition_type_declarations(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_type_declarations(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_type_declaration_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_type_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_type_declaration_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_type_declaration_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_type_declaration_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_TYPE_DECLARATION_CAPSULE_NAME, ifcopenshell_type_declaration_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_type_declaration_free(item); + Py_DECREF(values); + ifcopenshell_type_declaration_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_type_declaration_list_free(result); + return values; +} + +static PyObject* py_schema_definition_select_types(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_select_types(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_select_type_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_select_type_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_select_type_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_select_type_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_select_type_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_SELECT_TYPE_CAPSULE_NAME, ifcopenshell_select_type_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_select_type_free(item); + Py_DECREF(values); + ifcopenshell_select_type_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_select_type_list_free(result); + return values; +} + +static PyObject* py_schema_definition_enumeration_types(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_enumeration_types(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_enumeration_type_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_enumeration_type_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_enumeration_type_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_enumeration_type_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_enumeration_type_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_ENUMERATION_TYPE_CAPSULE_NAME, ifcopenshell_enumeration_type_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_enumeration_type_free(item); + Py_DECREF(values); + ifcopenshell_enumeration_type_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_enumeration_type_list_free(result); + return values; +} + +static PyObject* py_schema_definition_entities(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_schema_definition_entities(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_entity_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_entity_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_entity_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, IFCOPENSHELL_ENTITY_CAPSULE_NAME, ifcopenshell_entity_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_entity_free(item); + Py_DECREF(values); + ifcopenshell_entity_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_entity_list_free(result); + return values; +} + +static PyObject* py_schema_definition_name(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_schema_definition_name(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyObject* py_base_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_base_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); +} + +static PyObject* py_base_declaration(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_BASE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_base_declaration(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_base_unset_attribute_value(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int attribute_index = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &attribute_index)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_BASE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_base_unset_attribute_value(handle, attribute_index); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_base_identity(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_BASE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_base_identity(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_base_id(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_BASE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_base_id(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_entity_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_entity_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_ENTITY_CAPSULE_NAME, express_entity_capsule_destructor); +} + +static PyObject* py_entity_get_inverse(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* attribute_name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &attribute_name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_ENTITY_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_entity_get_inverse(handle, attribute_name); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_express_entity_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_express_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_express_entity_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_express_entity_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_express_entity_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, EXPRESS_ENTITY_CAPSULE_NAME, express_entity_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_express_entity_free(item); + Py_DECREF(values); + ifcopenshell_express_entity_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_express_entity_list_free(result); + return values; +} + +static PyObject* py_select_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_select_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_SELECT_CAPSULE_NAME, express_select_capsule_destructor); +} + +static PyObject* py_select_concrete(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, EXPRESS_SELECT_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_select_concrete(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); +} + +static PyObject* py_declared_type_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_declared_type_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_DECLARED_TYPE_CAPSULE_NAME, express_declared_type_capsule_destructor); +} + +static PyObject* py_full_buffer_impl_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_full_buffer_impl_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME, ifcopenshell_full_buffer_impl_capsule_destructor); +} + +static PyObject* py_full_buffer_impl_new_with_path(PyObject*, PyObject* args) { + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "s", &path)) { + return nullptr; + } + auto* result = ifcopenshell_full_buffer_impl_new_with_path(path); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME, ifcopenshell_full_buffer_impl_capsule_destructor); +} + +static PyObject* py_full_buffer_impl_size(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_full_buffer_impl_size(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_full_buffer_impl_get_u32(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_full_buffer_impl_get_u32(handle, position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_full_buffer_impl_push_next_page(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* page_data = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &page_data)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_full_buffer_impl_push_next_page(handle, page_data); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_full_buffer_impl_drop_pages(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int up_to_position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &up_to_position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FULL_BUFFER_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_full_buffer_impl_drop_pages(handle, up_to_position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_paged_file_impl_new_with_path_page_size_page_capacity(PyObject*, PyObject* args) { + const char* path = nullptr; + int page_size = 0; + int page_capacity = 0; + if (!PyArg_ParseTuple(args, "sii", &path, &page_size, &page_capacity)) { + return nullptr; + } + auto* result = ifcopenshell_paged_file_impl_new_with_path_page_size_page_capacity(path, page_size, page_capacity); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME, ifcopenshell_paged_file_impl_capsule_destructor); +} + +static PyObject* py_paged_file_impl_size(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_paged_file_impl_size(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_paged_file_impl_get_u32(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_paged_file_impl_get_u32(handle, position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_paged_file_impl_push_next_page(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* page_data = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &page_data)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_paged_file_impl_push_next_page(handle, page_data); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_paged_file_impl_drop_pages(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int up_to_position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &up_to_position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PAGED_FILE_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_paged_file_impl_drop_pages(handle, up_to_position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_pushed_sequential_impl_size(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_pushed_sequential_impl_size(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_pushed_sequential_impl_get_u32(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_pushed_sequential_impl_get_u32(handle, position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_pushed_sequential_impl_push_next_page(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* page_data = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &page_data)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_pushed_sequential_impl_push_next_page(handle, page_data); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_pushed_sequential_impl_drop_pages(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int up_to_position = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &up_to_position)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_PUSHED_SEQUENTIAL_IMPL_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_pushed_sequential_impl_drop_pages(handle, up_to_position); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_character_encoder_new_with_input(PyObject*, PyObject* args) { + const char* input = nullptr; + if (!PyArg_ParseTuple(args, "s", &input)) { + return nullptr; + } + auto* result = ifcopenshell_character_encoder_new_with_input(input); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_CHARACTER_ENCODER_CAPSULE_NAME, ifcopenshell_character_encoder_capsule_destructor); +} + +static PyObject* py_file_new_with_path(PyObject*, PyObject* args) { + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "s", &path)) { + return nullptr; + } + auto* result = ifcopenshell_file_new_with_path(path); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FILE_CAPSULE_NAME, ifcopenshell_file_capsule_destructor); +} + +static PyObject* py_file_new_with_path_with_filetype(PyObject*, PyObject* args) { + const char* path = nullptr; + int filetype = 0; + if (!PyArg_ParseTuple(args, "si", &path, &filetype)) { + return nullptr; + } + auto* result = ifcopenshell_file_new_with_path_with_filetype(path, static_cast(filetype)); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FILE_CAPSULE_NAME, ifcopenshell_file_capsule_destructor); +} + +static PyObject* py_file_new_with_path_with_filetype_readonly(PyObject*, PyObject* args) { + const char* path = nullptr; + int filetype = 0; + int readonly = 0; + if (!PyArg_ParseTuple(args, "sip", &path, &filetype, &readonly)) { + return nullptr; + } + auto* result = ifcopenshell_file_new_with_path_with_filetype_readonly(path, static_cast(filetype), readonly); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FILE_CAPSULE_NAME, ifcopenshell_file_capsule_destructor); +} + +static PyObject* py_file_initialize(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &path)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_file_initialize(handle, path); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_file_initialize_with_filetype(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* path = nullptr; + int filetype = 0; + if (!PyArg_ParseTuple(args, "Osi", &self_capsule, &path, &filetype)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_file_initialize_with_filetype(handle, path, static_cast(filetype)); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_file_initialize_with_filetype_readonly(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* path = nullptr; + int filetype = 0; + int readonly = 0; + if (!PyArg_ParseTuple(args, "Osip", &self_capsule, &path, &filetype, &readonly)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + bool result = ifcopenshell_file_initialize_with_filetype_readonly(handle, path, static_cast(filetype), readonly); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyBool_FromLong(result ? 1 : 0); +} + +static PyObject* py_file_bypass_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* type_name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &type_name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_bypass_type(handle, type_name); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_file_good(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_good(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_FILE_OPEN_STATUS_CAPSULE_NAME, ifcopenshell_file_open_status_capsule_destructor); +} + +static PyObject* py_file_instances_by_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* type_name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &type_name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_instances_by_type(handle, type_name); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_express_base_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_express_base_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_express_base_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_express_base_free(item); + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_express_base_list_free(result); + return values; +} + +static PyObject* py_file_instances_by_type_excl_subtypes(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* type_name = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &type_name)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_instances_by_type_excl_subtypes(handle, type_name); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_express_base_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_express_base_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_express_base_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_express_base_free(item); + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_express_base_list_free(result); + return values; +} + +static PyObject* py_file_instances_by_reference(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int reference_id = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &reference_id)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_instances_by_reference(handle, reference_id); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + int size = ifcopenshell_express_base_list_size(result); + if (ifcopenshell_last_error_message() != nullptr) { + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* values = PyList_New(size); + if (values == nullptr) { + ifcopenshell_express_base_list_free(result); + return nullptr; + } + for (int index = 0; index < size; ++index) { + auto* item = ifcopenshell_express_base_list_get(result, index); + if (item == nullptr) { + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return raise_last_error("Native call failed"); + } + PyObject* capsule = PyCapsule_New(item, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); + if (capsule == nullptr) { + ifcopenshell_express_base_free(item); + Py_DECREF(values); + ifcopenshell_express_base_list_free(result); + return nullptr; + } + PyList_SET_ITEM(values, index, capsule); + } + ifcopenshell_express_base_list_free(result); + return values; +} + +static PyObject* py_file_instance_by_id(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int instance_id = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &instance_id)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_instance_by_id(handle, instance_id); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); +} + +static PyObject* py_file_instance_by_guid(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + const char* global_id = nullptr; + if (!PyArg_ParseTuple(args, "Os", &self_capsule, &global_id)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_instance_by_guid(handle, global_id); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, EXPRESS_BASE_CAPSULE_NAME, express_base_capsule_destructor); +} + +static PyObject* py_file_get_total_inverses(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + int instance_id = 0; + if (!PyArg_ParseTuple(args, "Oi", &self_capsule, &instance_id)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_file_get_total_inverses(handle, instance_id); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_file_fresh_id(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_file_fresh_id(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_file_get_max_id(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + int result = ifcopenshell_file_get_max_id(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + return PyLong_FromLong(result); +} + +static PyObject* py_file_ifcroot_type(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_ifcroot_type(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_DECLARATION_CAPSULE_NAME, ifcopenshell_declaration_capsule_destructor); +} + +static PyObject* py_file_recalculate_id_counter(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_recalculate_id_counter(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_file_header(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_header(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SPF_HEADER_CAPSULE_NAME, ifcopenshell_spf_header_capsule_destructor); +} + +static PyObject* py_file_schema(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + auto* result = ifcopenshell_file_schema(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_SCHEMA_DEFINITION_CAPSULE_NAME, ifcopenshell_schema_definition_capsule_destructor); +} + +static PyObject* py_file_build_inverses(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_build_inverses(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_file_batch(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_batch(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_file_unbatch(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_unbatch(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_file_reset_identity_cache(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_FILE_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + ifcopenshell_file_reset_identity_cache(handle); + if (ifcopenshell_last_error_message() != nullptr) { + return raise_last_error("Native call failed"); + } + Py_RETURN_NONE; +} + +static PyObject* py_global_id_new(PyObject*, PyObject* args) { + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + auto* result = ifcopenshell_global_id_new(); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_GLOBAL_ID_CAPSULE_NAME, ifcopenshell_global_id_capsule_destructor); +} + +static PyObject* py_global_id_new_with_value(PyObject*, PyObject* args) { + const char* value = nullptr; + if (!PyArg_ParseTuple(args, "s", &value)) { + return nullptr; + } + auto* result = ifcopenshell_global_id_new_with_value(value); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + return PyCapsule_New(result, IFCOPENSHELL_GLOBAL_ID_CAPSULE_NAME, ifcopenshell_global_id_capsule_destructor); +} + +static PyObject* py_global_id_formatted(PyObject*, PyObject* args) { + PyObject* self_capsule = nullptr; + auto* handle = static_cast(nullptr); + if (!PyArg_ParseTuple(args, "O", &self_capsule)) { + return nullptr; + } + handle = static_cast(PyCapsule_GetPointer(self_capsule, IFCOPENSHELL_GLOBAL_ID_CAPSULE_NAME)); + if (handle == nullptr) { + return nullptr; + } + char* result = ifcopenshell_global_id_formatted(handle); + if (result == nullptr) { + return raise_last_error("Native call failed"); + } + PyObject* value = PyUnicode_FromString(result); + ifcopenshell_string_free(result); + return value; +} + +static PyMethodDef MODULE_METHODS[] = { + {"exception_new_with_message", py_exception_new_with_message, METH_VARARGS, nullptr}, + {"attribute_out_of_range_exception_new_with_message", py_attribute_out_of_range_exception_new_with_message, METH_VARARGS, nullptr}, + {"invalid_token_exception_new_with_token_start_token_string_expected_type", py_invalid_token_exception_new_with_token_start_token_string_expected_type, METH_VARARGS, nullptr}, + {"parameter_type_as_named_type", py_parameter_type_as_named_type, METH_VARARGS, nullptr}, + {"parameter_type_as_simple_type", py_parameter_type_as_simple_type, METH_VARARGS, nullptr}, + {"parameter_type_as_aggregation_type", py_parameter_type_as_aggregation_type, METH_VARARGS, nullptr}, + {"parameter_type_is", py_parameter_type_is, METH_VARARGS, nullptr}, + {"named_type_declared_type", py_named_type_declared_type, METH_VARARGS, nullptr}, + {"named_type_as_named_type", py_named_type_as_named_type, METH_VARARGS, nullptr}, + {"named_type_is", py_named_type_is, METH_VARARGS, nullptr}, + {"simple_type_as_simple_type", py_simple_type_as_simple_type, METH_VARARGS, nullptr}, + {"aggregation_type_bound1", py_aggregation_type_bound1, METH_VARARGS, nullptr}, + {"aggregation_type_bound2", py_aggregation_type_bound2, METH_VARARGS, nullptr}, + {"aggregation_type_type_of_element", py_aggregation_type_type_of_element, METH_VARARGS, nullptr}, + {"aggregation_type_as_aggregation_type", py_aggregation_type_as_aggregation_type, METH_VARARGS, nullptr}, + {"declaration_new_with_name_index_in_schema", py_declaration_new_with_name_index_in_schema, METH_VARARGS, nullptr}, + {"declaration_name", py_declaration_name, METH_VARARGS, nullptr}, + {"declaration_name_uc", py_declaration_name_uc, METH_VARARGS, nullptr}, + {"declaration_as_type_declaration", py_declaration_as_type_declaration, METH_VARARGS, nullptr}, + {"declaration_as_select_type", py_declaration_as_select_type, METH_VARARGS, nullptr}, + {"declaration_as_enumeration_type", py_declaration_as_enumeration_type, METH_VARARGS, nullptr}, + {"declaration_as_entity", py_declaration_as_entity, METH_VARARGS, nullptr}, + {"declaration_is", py_declaration_is, METH_VARARGS, nullptr}, + {"declaration_index_in_schema", py_declaration_index_in_schema, METH_VARARGS, nullptr}, + {"declaration_type", py_declaration_type, METH_VARARGS, nullptr}, + {"declaration_schema", py_declaration_schema, METH_VARARGS, nullptr}, + {"type_declaration_declared_type", py_type_declaration_declared_type, METH_VARARGS, nullptr}, + {"type_declaration_as_type_declaration", py_type_declaration_as_type_declaration, METH_VARARGS, nullptr}, + {"select_type_select_list", py_select_type_select_list, METH_VARARGS, nullptr}, + {"select_type_as_select_type", py_select_type_as_select_type, METH_VARARGS, nullptr}, + {"enumeration_type_lookup_enum_offset", py_enumeration_type_lookup_enum_offset, METH_VARARGS, nullptr}, + {"enumeration_type_as_enumeration_type", py_enumeration_type_as_enumeration_type, METH_VARARGS, nullptr}, + {"attribute_name", py_attribute_name, METH_VARARGS, nullptr}, + {"attribute_type_of_attribute", py_attribute_type_of_attribute, METH_VARARGS, nullptr}, + {"attribute_optional", py_attribute_optional, METH_VARARGS, nullptr}, + {"inverse_attribute_name", py_inverse_attribute_name, METH_VARARGS, nullptr}, + {"inverse_attribute_bound1", py_inverse_attribute_bound1, METH_VARARGS, nullptr}, + {"inverse_attribute_bound2", py_inverse_attribute_bound2, METH_VARARGS, nullptr}, + {"inverse_attribute_entity_reference", py_inverse_attribute_entity_reference, METH_VARARGS, nullptr}, + {"inverse_attribute_attribute_reference", py_inverse_attribute_attribute_reference, METH_VARARGS, nullptr}, + {"entity_is_abstract", py_entity_is_abstract, METH_VARARGS, nullptr}, + {"entity_subtypes", py_entity_subtypes, METH_VARARGS, nullptr}, + {"entity_attributes", py_entity_attributes, METH_VARARGS, nullptr}, + {"entity_all_attributes", py_entity_all_attributes, METH_VARARGS, nullptr}, + {"entity_all_inverse_attributes", py_entity_all_inverse_attributes, METH_VARARGS, nullptr}, + {"entity_attribute_by_index", py_entity_attribute_by_index, METH_VARARGS, nullptr}, + {"entity_attribute_count", py_entity_attribute_count, METH_VARARGS, nullptr}, + {"entity_supertype", py_entity_supertype, METH_VARARGS, nullptr}, + {"entity_as_entity", py_entity_as_entity, METH_VARARGS, nullptr}, + {"schema_definition_declaration_by_name_with_name", py_schema_definition_declaration_by_name_with_name, METH_VARARGS, nullptr}, + {"schema_definition_declaration_by_name_with_declaration_index", py_schema_definition_declaration_by_name_with_declaration_index, METH_VARARGS, nullptr}, + {"schema_definition_declarations", py_schema_definition_declarations, METH_VARARGS, nullptr}, + {"schema_definition_type_declarations", py_schema_definition_type_declarations, METH_VARARGS, nullptr}, + {"schema_definition_select_types", py_schema_definition_select_types, METH_VARARGS, nullptr}, + {"schema_definition_enumeration_types", py_schema_definition_enumeration_types, METH_VARARGS, nullptr}, + {"schema_definition_entities", py_schema_definition_entities, METH_VARARGS, nullptr}, + {"schema_definition_name", py_schema_definition_name, METH_VARARGS, nullptr}, + {"base_new", py_base_new, METH_VARARGS, nullptr}, + {"base_declaration", py_base_declaration, METH_VARARGS, nullptr}, + {"base_unset_attribute_value", py_base_unset_attribute_value, METH_VARARGS, nullptr}, + {"base_identity", py_base_identity, METH_VARARGS, nullptr}, + {"base_id", py_base_id, METH_VARARGS, nullptr}, + {"entity_new", py_entity_new, METH_VARARGS, nullptr}, + {"entity_get_inverse", py_entity_get_inverse, METH_VARARGS, nullptr}, + {"select_new", py_select_new, METH_VARARGS, nullptr}, + {"select_concrete", py_select_concrete, METH_VARARGS, nullptr}, + {"declared_type_new", py_declared_type_new, METH_VARARGS, nullptr}, + {"full_buffer_impl_new", py_full_buffer_impl_new, METH_VARARGS, nullptr}, + {"full_buffer_impl_new_with_path", py_full_buffer_impl_new_with_path, METH_VARARGS, nullptr}, + {"full_buffer_impl_size", py_full_buffer_impl_size, METH_VARARGS, nullptr}, + {"full_buffer_impl_get_u32", py_full_buffer_impl_get_u32, METH_VARARGS, nullptr}, + {"full_buffer_impl_push_next_page", py_full_buffer_impl_push_next_page, METH_VARARGS, nullptr}, + {"full_buffer_impl_drop_pages", py_full_buffer_impl_drop_pages, METH_VARARGS, nullptr}, + {"paged_file_impl_new_with_path_page_size_page_capacity", py_paged_file_impl_new_with_path_page_size_page_capacity, METH_VARARGS, nullptr}, + {"paged_file_impl_size", py_paged_file_impl_size, METH_VARARGS, nullptr}, + {"paged_file_impl_get_u32", py_paged_file_impl_get_u32, METH_VARARGS, nullptr}, + {"paged_file_impl_push_next_page", py_paged_file_impl_push_next_page, METH_VARARGS, nullptr}, + {"paged_file_impl_drop_pages", py_paged_file_impl_drop_pages, METH_VARARGS, nullptr}, + {"pushed_sequential_impl_size", py_pushed_sequential_impl_size, METH_VARARGS, nullptr}, + {"pushed_sequential_impl_get_u32", py_pushed_sequential_impl_get_u32, METH_VARARGS, nullptr}, + {"pushed_sequential_impl_push_next_page", py_pushed_sequential_impl_push_next_page, METH_VARARGS, nullptr}, + {"pushed_sequential_impl_drop_pages", py_pushed_sequential_impl_drop_pages, METH_VARARGS, nullptr}, + {"character_encoder_new_with_input", py_character_encoder_new_with_input, METH_VARARGS, nullptr}, + {"file_new_with_path", py_file_new_with_path, METH_VARARGS, nullptr}, + {"file_new_with_path_with_filetype", py_file_new_with_path_with_filetype, METH_VARARGS, nullptr}, + {"file_new_with_path_with_filetype_readonly", py_file_new_with_path_with_filetype_readonly, METH_VARARGS, nullptr}, + {"file_initialize", py_file_initialize, METH_VARARGS, nullptr}, + {"file_initialize_with_filetype", py_file_initialize_with_filetype, METH_VARARGS, nullptr}, + {"file_initialize_with_filetype_readonly", py_file_initialize_with_filetype_readonly, METH_VARARGS, nullptr}, + {"file_bypass_type", py_file_bypass_type, METH_VARARGS, nullptr}, + {"file_good", py_file_good, METH_VARARGS, nullptr}, + {"file_instances_by_type", py_file_instances_by_type, METH_VARARGS, nullptr}, + {"file_instances_by_type_excl_subtypes", py_file_instances_by_type_excl_subtypes, METH_VARARGS, nullptr}, + {"file_instances_by_reference", py_file_instances_by_reference, METH_VARARGS, nullptr}, + {"file_instance_by_id", py_file_instance_by_id, METH_VARARGS, nullptr}, + {"file_instance_by_guid", py_file_instance_by_guid, METH_VARARGS, nullptr}, + {"file_get_total_inverses", py_file_get_total_inverses, METH_VARARGS, nullptr}, + {"file_fresh_id", py_file_fresh_id, METH_VARARGS, nullptr}, + {"file_get_max_id", py_file_get_max_id, METH_VARARGS, nullptr}, + {"file_ifcroot_type", py_file_ifcroot_type, METH_VARARGS, nullptr}, + {"file_recalculate_id_counter", py_file_recalculate_id_counter, METH_VARARGS, nullptr}, + {"file_header", py_file_header, METH_VARARGS, nullptr}, + {"file_schema", py_file_schema, METH_VARARGS, nullptr}, + {"file_build_inverses", py_file_build_inverses, METH_VARARGS, nullptr}, + {"file_batch", py_file_batch, METH_VARARGS, nullptr}, + {"file_unbatch", py_file_unbatch, METH_VARARGS, nullptr}, + {"file_reset_identity_cache", py_file_reset_identity_cache, METH_VARARGS, nullptr}, + {"global_id_new", py_global_id_new, METH_VARARGS, nullptr}, + {"global_id_new_with_value", py_global_id_new_with_value, METH_VARARGS, nullptr}, + {"global_id_formatted", py_global_id_formatted, METH_VARARGS, nullptr}, + {nullptr, nullptr, 0, nullptr}, +}; + +static PyModuleDef MODULE_DEF = { + PyModuleDef_HEAD_INIT, + "_ifcopenshell_experimental", + nullptr, + -1, + MODULE_METHODS, +}; + +PyMODINIT_FUNC PyInit__ifcopenshell_experimental(void) { + PyObject* module = PyModule_Create(&MODULE_DEF); + if (module == nullptr) { + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_IFCSPF", IFCOPENSHELL_FILE_TYPE_T_FT_IFCSPF) < 0) { + Py_DECREF(module); + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_IFCXML", IFCOPENSHELL_FILE_TYPE_T_FT_IFCXML) < 0) { + Py_DECREF(module); + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_IFCZIP", IFCOPENSHELL_FILE_TYPE_T_FT_IFCZIP) < 0) { + Py_DECREF(module); + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_ROCKSDB", IFCOPENSHELL_FILE_TYPE_T_FT_ROCKSDB) < 0) { + Py_DECREF(module); + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_UNKNOWN", IFCOPENSHELL_FILE_TYPE_T_FT_UNKNOWN) < 0) { + Py_DECREF(module); + return nullptr; + } + if (PyModule_AddIntConstant(module, "FT_AUTODETECT", IFCOPENSHELL_FILE_TYPE_T_FT_AUTODETECT) < 0) { + Py_DECREF(module); + return nullptr; + } + return module; +} diff --git a/src/wrappergen/generated/ifcopenshell_experimental.py b/src/wrappergen/generated/ifcopenshell_experimental.py new file mode 100644 index 0000000000..6c187b3f70 --- /dev/null +++ b/src/wrappergen/generated/ifcopenshell_experimental.py @@ -0,0 +1,525 @@ +from __future__ import annotations + +from enum import IntEnum + +import _ifcopenshell_experimental as _native + +class FileType(IntEnum): + FT_IFCSPF = _native.FT_IFCSPF + FT_IFCXML = _native.FT_IFCXML + FT_IFCZIP = _native.FT_IFCZIP + FT_ROCKSDB = _native.FT_ROCKSDB + FT_UNKNOWN = _native.FT_UNKNOWN + FT_AUTODETECT = _native.FT_AUTODETECT + +class exception: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_message(message: str) -> exception: + return exception(_native.exception_new_with_message(message)) + +class attribute_out_of_range_exception: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_message(message: str) -> attribute_out_of_range_exception: + return attribute_out_of_range_exception(_native.attribute_out_of_range_exception_new_with_message(message)) + +class invalid_token_exception: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_token_start_token_string_expected_type(token_start: int, token_string: str, expected_type: str) -> invalid_token_exception: + return invalid_token_exception(_native.invalid_token_exception_new_with_token_start_token_string_expected_type(token_start, token_string, expected_type)) + +class parameter_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def as_named_type(self) -> named_type: + return named_type(_native.parameter_type_as_named_type(self._handle)) + + def as_simple_type(self) -> simple_type: + return simple_type(_native.parameter_type_as_simple_type(self._handle)) + + def as_aggregation_type(self) -> aggregation_type: + return aggregation_type(_native.parameter_type_as_aggregation_type(self._handle)) + + def is_(self, arg0: str) -> bool: + return _native.parameter_type_is(self._handle, arg0) + +class named_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def declared_type(self) -> declaration: + return declaration(_native.named_type_declared_type(self._handle)) + + def as_named_type(self) -> named_type: + return named_type(_native.named_type_as_named_type(self._handle)) + + def is_(self, name: str) -> bool: + return _native.named_type_is(self._handle, name) + +class simple_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def as_simple_type(self) -> simple_type: + return simple_type(_native.simple_type_as_simple_type(self._handle)) + +class aggregation_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def bound1(self) -> int: + return _native.aggregation_type_bound1(self._handle) + + def bound2(self) -> int: + return _native.aggregation_type_bound2(self._handle) + + def type_of_element(self) -> parameter_type: + return parameter_type(_native.aggregation_type_type_of_element(self._handle)) + + def as_aggregation_type(self) -> aggregation_type: + return aggregation_type(_native.aggregation_type_as_aggregation_type(self._handle)) + +class declaration: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_name_index_in_schema(name: str, index_in_schema: int) -> declaration: + return declaration(_native.declaration_new_with_name_index_in_schema(name, index_in_schema)) + + def name(self) -> str: + return _native.declaration_name(self._handle) + + def name_uc(self) -> str: + return _native.declaration_name_uc(self._handle) + + def as_type_declaration(self) -> type_declaration: + return type_declaration(_native.declaration_as_type_declaration(self._handle)) + + def as_select_type(self) -> select_type: + return select_type(_native.declaration_as_select_type(self._handle)) + + def as_enumeration_type(self) -> enumeration_type: + return enumeration_type(_native.declaration_as_enumeration_type(self._handle)) + + def as_entity(self) -> entity: + return entity(_native.declaration_as_entity(self._handle)) + + def is_(self, name: str) -> bool: + return _native.declaration_is(self._handle, name) + + def index_in_schema(self) -> int: + return _native.declaration_index_in_schema(self._handle) + + def type(self) -> int: + return _native.declaration_type(self._handle) + + def schema(self) -> schema_definition: + return schema_definition(_native.declaration_schema(self._handle)) + +class type_declaration: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def declared_type(self) -> parameter_type: + return parameter_type(_native.type_declaration_declared_type(self._handle)) + + def as_type_declaration(self) -> type_declaration: + return type_declaration(_native.type_declaration_as_type_declaration(self._handle)) + +class select_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def select_list(self) -> list[declaration]: + return [declaration(item) for item in _native.select_type_select_list(self._handle)] + + def as_select_type(self) -> select_type: + return select_type(_native.select_type_as_select_type(self._handle)) + +class enumeration_type: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def lookup_enum_offset(self, value_name: str) -> int: + return _native.enumeration_type_lookup_enum_offset(self._handle, value_name) + + def as_enumeration_type(self) -> enumeration_type: + return enumeration_type(_native.enumeration_type_as_enumeration_type(self._handle)) + +class attribute: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def name(self) -> str: + return _native.attribute_name(self._handle) + + def type_of_attribute(self) -> parameter_type: + return parameter_type(_native.attribute_type_of_attribute(self._handle)) + + def optional(self) -> bool: + return _native.attribute_optional(self._handle) + +class inverse_attribute: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def name(self) -> str: + return _native.inverse_attribute_name(self._handle) + + def bound1(self) -> int: + return _native.inverse_attribute_bound1(self._handle) + + def bound2(self) -> int: + return _native.inverse_attribute_bound2(self._handle) + + def entity_reference(self) -> entity: + return entity(_native.inverse_attribute_entity_reference(self._handle)) + + def attribute_reference(self) -> attribute: + return attribute(_native.inverse_attribute_attribute_reference(self._handle)) + +class entity: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def is_abstract(self) -> bool: + return _native.entity_is_abstract(self._handle) + + def subtypes(self) -> list[entity]: + return [entity(item) for item in _native.entity_subtypes(self._handle)] + + def attributes(self) -> list[attribute]: + return [attribute(item) for item in _native.entity_attributes(self._handle)] + + def all_attributes(self) -> list[attribute]: + return [attribute(item) for item in _native.entity_all_attributes(self._handle)] + + def all_inverse_attributes(self) -> list[inverse_attribute]: + return [inverse_attribute(item) for item in _native.entity_all_inverse_attributes(self._handle)] + + def attribute_by_index(self, index: int) -> attribute: + return attribute(_native.entity_attribute_by_index(self._handle, index)) + + def attribute_count(self) -> int: + return _native.entity_attribute_count(self._handle) + + def supertype(self) -> entity: + return entity(_native.entity_supertype(self._handle)) + + def as_entity(self) -> entity: + return entity(_native.entity_as_entity(self._handle)) + +class schema_definition: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def declaration_by_name_with_name(self, name: str) -> declaration: + return declaration(_native.schema_definition_declaration_by_name_with_name(self._handle, name)) + + def declaration_by_name_with_declaration_index(self, declaration_index: int) -> declaration: + return declaration(_native.schema_definition_declaration_by_name_with_declaration_index(self._handle, declaration_index)) + + def declarations(self) -> list[declaration]: + return [declaration(item) for item in _native.schema_definition_declarations(self._handle)] + + def type_declarations(self) -> list[type_declaration]: + return [type_declaration(item) for item in _native.schema_definition_type_declarations(self._handle)] + + def select_types(self) -> list[select_type]: + return [select_type(item) for item in _native.schema_definition_select_types(self._handle)] + + def enumeration_types(self) -> list[enumeration_type]: + return [enumeration_type(item) for item in _native.schema_definition_enumeration_types(self._handle)] + + def entities(self) -> list[entity]: + return [entity(item) for item in _native.schema_definition_entities(self._handle)] + + def name(self) -> str: + return _native.schema_definition_name(self._handle) + +class Base: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> Base: + return Base(_native.base_new()) + + def declaration(self) -> declaration: + return declaration(_native.base_declaration(self._handle)) + + def unset_attribute_value(self, attribute_index: int) -> None: + _native.base_unset_attribute_value(self._handle, attribute_index) + return None + + def identity(self) -> int: + return _native.base_identity(self._handle) + + def id(self) -> int: + return _native.base_id(self._handle) + +class Entity: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> Entity: + return Entity(_native.entity_new()) + + def get_inverse(self, attribute_name: str) -> list[Entity]: + return [Entity(item) for item in _native.entity_get_inverse(self._handle, attribute_name)] + +class Select: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> Select: + return Select(_native.select_new()) + + def concrete(self) -> Base: + return Base(_native.select_concrete(self._handle)) + +class DeclaredType: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> DeclaredType: + return DeclaredType(_native.declared_type_new()) + +class full_buffer_impl: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> full_buffer_impl: + return full_buffer_impl(_native.full_buffer_impl_new()) + + @staticmethod + def with_path(path: str) -> full_buffer_impl: + return full_buffer_impl(_native.full_buffer_impl_new_with_path(path)) + + def size(self) -> int: + return _native.full_buffer_impl_size(self._handle) + + def get_u32(self, position: int) -> int: + return _native.full_buffer_impl_get_u32(self._handle, position) + + def push_next_page(self, page_data: str) -> None: + _native.full_buffer_impl_push_next_page(self._handle, page_data) + return None + + def drop_pages(self, up_to_position: int) -> None: + _native.full_buffer_impl_drop_pages(self._handle, up_to_position) + return None + +class paged_file_impl: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_path_page_size_page_capacity(path: str, page_size: int, page_capacity: int) -> paged_file_impl: + return paged_file_impl(_native.paged_file_impl_new_with_path_page_size_page_capacity(path, page_size, page_capacity)) + + def size(self) -> int: + return _native.paged_file_impl_size(self._handle) + + def get_u32(self, position: int) -> int: + return _native.paged_file_impl_get_u32(self._handle, position) + + def push_next_page(self, page_data: str) -> None: + _native.paged_file_impl_push_next_page(self._handle, page_data) + return None + + def drop_pages(self, up_to_position: int) -> None: + _native.paged_file_impl_drop_pages(self._handle, up_to_position) + return None + +class pushed_sequential_impl: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + def size(self) -> int: + return _native.pushed_sequential_impl_size(self._handle) + + def get_u32(self, position: int) -> int: + return _native.pushed_sequential_impl_get_u32(self._handle, position) + + def push_next_page(self, page_data: str) -> None: + _native.pushed_sequential_impl_push_next_page(self._handle, page_data) + return None + + def drop_pages(self, up_to_position: int) -> None: + _native.pushed_sequential_impl_drop_pages(self._handle, up_to_position) + return None + +class character_encoder: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_input(input: str) -> character_encoder: + return character_encoder(_native.character_encoder_new_with_input(input)) + +class file_open_status: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + pass + +class spf_header: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + pass + +class file: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def with_path(path: str, filetype: FileType = FileType.FT_AUTODETECT, readonly: bool = False) -> file: + return file(_native.file_new_with_path_with_filetype_readonly(path, int(filetype), readonly)) + + def initialize(self, path: str, filetype: FileType = FileType.FT_AUTODETECT, readonly: bool = False) -> bool: + return _native.file_initialize_with_filetype_readonly(self._handle, path, int(filetype), readonly) + + def bypass_type(self, type_name: str) -> None: + _native.file_bypass_type(self._handle, type_name) + return None + + def good(self) -> file_open_status: + return file_open_status(_native.file_good(self._handle)) + + def instances_by_type(self, type_name: str) -> list[Base]: + return [Base(item) for item in _native.file_instances_by_type(self._handle, type_name)] + + def instances_by_type_excl_subtypes(self, type_name: str) -> list[Base]: + return [Base(item) for item in _native.file_instances_by_type_excl_subtypes(self._handle, type_name)] + + def instances_by_reference(self, reference_id: int) -> list[Base]: + return [Base(item) for item in _native.file_instances_by_reference(self._handle, reference_id)] + + def instance_by_id(self, instance_id: int) -> Base: + return Base(_native.file_instance_by_id(self._handle, instance_id)) + + def instance_by_guid(self, global_id: str) -> Base: + return Base(_native.file_instance_by_guid(self._handle, global_id)) + + def get_total_inverses(self, instance_id: int) -> int: + return _native.file_get_total_inverses(self._handle, instance_id) + + def fresh_id(self) -> int: + return _native.file_fresh_id(self._handle) + + def get_max_id(self) -> int: + return _native.file_get_max_id(self._handle) + + def ifcroot_type(self) -> declaration: + return declaration(_native.file_ifcroot_type(self._handle)) + + def recalculate_id_counter(self) -> None: + _native.file_recalculate_id_counter(self._handle) + return None + + def header(self) -> spf_header: + return spf_header(_native.file_header(self._handle)) + + def schema(self) -> schema_definition: + return schema_definition(_native.file_schema(self._handle)) + + def build_inverses(self) -> None: + _native.file_build_inverses(self._handle) + return None + + def batch(self) -> None: + _native.file_batch(self._handle) + return None + + def unbatch(self) -> None: + _native.file_unbatch(self._handle) + return None + + def reset_identity_cache(self) -> None: + _native.file_reset_identity_cache(self._handle) + return None + +class global_id: + __slots__ = ("_handle",) + + def __init__(self, handle) -> None: + self._handle = handle + + @staticmethod + def create() -> global_id: + return global_id(_native.global_id_new()) + + @staticmethod + def with_value(value: str) -> global_id: + return global_id(_native.global_id_new_with_value(value)) + + def formatted(self) -> str: + return _native.global_id_formatted(self._handle) diff --git a/src/wrappergen/generated/ifcopenshell_experimental_c_api.cpp b/src/wrappergen/generated/ifcopenshell_experimental_c_api.cpp new file mode 100644 index 0000000000..d653587630 --- /dev/null +++ b/src/wrappergen/generated/ifcopenshell_experimental_c_api.cpp @@ -0,0 +1,2253 @@ +#include "ifcopenshell_experimental_c_api.h" + +#include "character_decoder.h" +#include "exception.h" +#include "express.h" +#include "file.h" +#include "file_open_status.h" +#include "file_reader.h" +#include "global_id.h" +#include "schema.h" +#include "spf_header.h" + +#include +#include +#include +#include +#include +#include + +namespace { +thread_local std::string g_last_error; + +char* duplicate_string(const std::string& value) { + auto* buffer = new char[value.size() + 1]; + std::copy(value.begin(), value.end(), buffer); + buffer[value.size()] = '\0'; + return buffer; +} + +void set_last_error(const std::exception& exception) { + g_last_error = exception.what(); +} +} + +struct ifcopenshell_exception_t { + ifcopenshell::exception value; +}; + +struct ifcopenshell_attribute_out_of_range_exception_t { + ifcopenshell::attribute_out_of_range_exception value; +}; + +struct ifcopenshell_invalid_token_exception_t { + ifcopenshell::invalid_token_exception value; +}; + +struct ifcopenshell_parameter_type_t { + ifcopenshell::parameter_type value; +}; + +struct ifcopenshell_named_type_t { + ifcopenshell::named_type value; +}; + +struct ifcopenshell_simple_type_t { + ifcopenshell::simple_type value; +}; + +struct ifcopenshell_aggregation_type_t { + ifcopenshell::aggregation_type value; +}; + +struct ifcopenshell_declaration_t { + ifcopenshell::declaration value; +}; + +struct ifcopenshell_type_declaration_t { + ifcopenshell::type_declaration value; +}; + +struct ifcopenshell_select_type_t { + ifcopenshell::select_type value; +}; + +struct ifcopenshell_enumeration_type_t { + ifcopenshell::enumeration_type value; +}; + +struct ifcopenshell_attribute_t { + ifcopenshell::attribute value; +}; + +struct ifcopenshell_inverse_attribute_t { + ifcopenshell::inverse_attribute value; +}; + +struct ifcopenshell_entity_t { + ifcopenshell::entity value; +}; + +struct ifcopenshell_schema_definition_t { + ifcopenshell::schema_definition value; +}; + +struct ifcopenshell_express_base_t { + std::shared_ptr owner; + express::Base value; +}; + +struct ifcopenshell_express_entity_t { + std::shared_ptr owner; + express::Entity value; +}; + +struct ifcopenshell_express_select_t { + std::shared_ptr owner; + express::Select value; +}; + +struct ifcopenshell_express_declared_type_t { + std::shared_ptr owner; + express::DeclaredType value; +}; + +struct ifcopenshell_full_buffer_impl_t { + ifcopenshell::full_buffer_impl value; +}; + +struct ifcopenshell_paged_file_impl_t { + ifcopenshell::paged_file_impl value; +}; + +struct ifcopenshell_pushed_sequential_impl_t { + ifcopenshell::pushed_sequential_impl value; +}; + +struct ifcopenshell_character_encoder_t { + ifcopenshell::character_encoder value; +}; + +struct ifcopenshell_file_open_status_t { + ifcopenshell::file_open_status value; +}; + +struct ifcopenshell_spf_header_t { + ifcopenshell::spf_header value; +}; + +struct ifcopenshell_file_t { + std::shared_ptr value; +}; + +struct ifcopenshell_global_id_t { + ifcopenshell::global_id value; +}; + +struct ifcopenshell_declaration_list_t { + std::vector value; +}; + +struct ifcopenshell_entity_list_t { + std::vector value; +}; + +struct ifcopenshell_attribute_list_t { + std::vector value; +}; + +struct ifcopenshell_inverse_attribute_list_t { + std::vector value; +}; + +struct ifcopenshell_type_declaration_list_t { + std::vector value; +}; + +struct ifcopenshell_select_type_list_t { + std::vector value; +}; + +struct ifcopenshell_enumeration_type_list_t { + std::vector value; +}; + +struct ifcopenshell_express_entity_list_t { + std::shared_ptr owner; + std::vector value; +}; + +struct ifcopenshell_express_base_list_t { + std::shared_ptr owner; + std::vector value; +}; + +extern "C" { + +const char* ifcopenshell_last_error_message(void) { + return g_last_error.empty() ? nullptr : g_last_error.c_str(); +} + +void ifcopenshell_last_error_clear(void) { + g_last_error.clear(); +} + +void ifcopenshell_string_free(char* value) { + delete[] value; +} + +ifcopenshell_exception_t* ifcopenshell_exception_new_with_message(const char* message) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::exception(std::string(message ? message : "")); + return new ifcopenshell_exception_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_attribute_out_of_range_exception_t* ifcopenshell_attribute_out_of_range_exception_new_with_message(const char* message) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::attribute_out_of_range_exception(std::string(message ? message : "")); + return new ifcopenshell_attribute_out_of_range_exception_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_invalid_token_exception_t* ifcopenshell_invalid_token_exception_new_with_token_start_token_string_expected_type(int token_start, const char* token_string, const char* expected_type) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::invalid_token_exception(token_start, std::string(token_string ? token_string : ""), std::string(expected_type ? expected_type : "")); + return new ifcopenshell_invalid_token_exception_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_named_type_t* ifcopenshell_parameter_type_as_named_type(ifcopenshell_parameter_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_named_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_named_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_simple_type_t* ifcopenshell_parameter_type_as_simple_type(ifcopenshell_parameter_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_simple_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_simple_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_aggregation_type_t* ifcopenshell_parameter_type_as_aggregation_type(ifcopenshell_parameter_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_aggregation_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_aggregation_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_parameter_type_is(ifcopenshell_parameter_type_t* handle, const char* arg0) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.is(std::string(arg0 ? arg0 : "")); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_declaration_t* ifcopenshell_named_type_declared_type(ifcopenshell_named_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.declared_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_named_type_t* ifcopenshell_named_type_as_named_type(ifcopenshell_named_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_named_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_named_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_named_type_is(ifcopenshell_named_type_t* handle, const char* name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.is(std::string(name ? name : "")); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_simple_type_t* ifcopenshell_simple_type_as_simple_type(ifcopenshell_simple_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_simple_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_simple_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_aggregation_type_bound1(ifcopenshell_aggregation_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.bound1(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_aggregation_type_bound2(ifcopenshell_aggregation_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.bound2(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_parameter_type_t* ifcopenshell_aggregation_type_type_of_element(ifcopenshell_aggregation_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.type_of_element(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_parameter_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_aggregation_type_t* ifcopenshell_aggregation_type_as_aggregation_type(ifcopenshell_aggregation_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_aggregation_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_aggregation_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_t* ifcopenshell_declaration_new_with_name_index_in_schema(const char* name, int index_in_schema) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::declaration(std::string(name ? name : ""), index_in_schema); + return new ifcopenshell_declaration_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +char* ifcopenshell_declaration_name(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.name(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +char* ifcopenshell_declaration_name_uc(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.name_uc(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_type_declaration_t* ifcopenshell_declaration_as_type_declaration(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_type_declaration(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_type_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_select_type_t* ifcopenshell_declaration_as_select_type(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_select_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_select_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_enumeration_type_t* ifcopenshell_declaration_as_enumeration_type(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_enumeration_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_enumeration_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_entity_t* ifcopenshell_declaration_as_entity(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_entity(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_entity_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_declaration_is(ifcopenshell_declaration_t* handle, const char* name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.is(std::string(name ? name : "")); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_declaration_index_in_schema(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.index_in_schema(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_declaration_type(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.type(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_schema_definition_t* ifcopenshell_declaration_schema(ifcopenshell_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.schema(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_schema_definition_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_parameter_type_t* ifcopenshell_type_declaration_declared_type(ifcopenshell_type_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.declared_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_parameter_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_type_declaration_t* ifcopenshell_type_declaration_as_type_declaration(ifcopenshell_type_declaration_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_type_declaration(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_type_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_list_t* ifcopenshell_select_type_select_list(ifcopenshell_select_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.select_list(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_declaration_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_select_type_t* ifcopenshell_select_type_as_select_type(ifcopenshell_select_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_select_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_select_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_enumeration_type_lookup_enum_offset(ifcopenshell_enumeration_type_t* handle, const char* value_name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.lookup_enum_offset(std::string(value_name ? value_name : "")); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_enumeration_type_t* ifcopenshell_enumeration_type_as_enumeration_type(ifcopenshell_enumeration_type_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_enumeration_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_enumeration_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +char* ifcopenshell_attribute_name(ifcopenshell_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.name(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_parameter_type_t* ifcopenshell_attribute_type_of_attribute(ifcopenshell_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.type_of_attribute(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_parameter_type_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_attribute_optional(ifcopenshell_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.optional(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +char* ifcopenshell_inverse_attribute_name(ifcopenshell_inverse_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.name(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_inverse_attribute_bound1(ifcopenshell_inverse_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.bound1(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_inverse_attribute_bound2(ifcopenshell_inverse_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.bound2(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_entity_t* ifcopenshell_inverse_attribute_entity_reference(ifcopenshell_inverse_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.entity_reference(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_entity_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_attribute_t* ifcopenshell_inverse_attribute_attribute_reference(ifcopenshell_inverse_attribute_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.attribute_reference(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_attribute_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_entity_is_abstract(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.is_abstract(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_entity_list_t* ifcopenshell_entity_subtypes(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.subtypes(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_entity_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_attribute_list_t* ifcopenshell_entity_attributes(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.attributes(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_attribute_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_attribute_list_t* ifcopenshell_entity_all_attributes(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.all_attributes(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_attribute_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_inverse_attribute_list_t* ifcopenshell_entity_all_inverse_attributes(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.all_inverse_attributes(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_inverse_attribute_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_attribute_t* ifcopenshell_entity_attribute_by_index(ifcopenshell_entity_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.attribute_by_index(index); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_attribute_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_entity_attribute_count(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.attribute_count(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_entity_t* ifcopenshell_entity_supertype(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.supertype(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_entity_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_entity_t* ifcopenshell_entity_as_entity(ifcopenshell_entity_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.as_entity(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_entity_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_t* ifcopenshell_schema_definition_declaration_by_name_with_name(ifcopenshell_schema_definition_t* handle, const char* name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.declaration_by_name(std::string(name ? name : "")); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_t* ifcopenshell_schema_definition_declaration_by_name_with_declaration_index(ifcopenshell_schema_definition_t* handle, int declaration_index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value.declaration_by_name(declaration_index); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_list_t* ifcopenshell_schema_definition_declarations(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.declarations(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_declaration_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_type_declaration_list_t* ifcopenshell_schema_definition_type_declarations(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.type_declarations(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_type_declaration_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_select_type_list_t* ifcopenshell_schema_definition_select_types(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.select_types(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_select_type_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_enumeration_type_list_t* ifcopenshell_schema_definition_enumeration_types(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.enumeration_types(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_enumeration_type_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_entity_list_t* ifcopenshell_schema_definition_entities(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto source_result = handle->value.entities(); + std::vector result; + result.reserve(source_result.size()); + for (const auto* item : source_result) { + if (item != nullptr) { + result.push_back(*item); + } + } + return new ifcopenshell_entity_list_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +char* ifcopenshell_schema_definition_name(ifcopenshell_schema_definition_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.name(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_t* ifcopenshell_base_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = express::Base(); + return new ifcopenshell_express_base_t{ {}, std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_declaration_t* ifcopenshell_base_declaration(ifcopenshell_express_base_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.declaration(); + return new ifcopenshell_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_base_unset_attribute_value(ifcopenshell_express_base_t* handle, int attribute_index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.unset_attribute_value(attribute_index); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +int ifcopenshell_base_identity(ifcopenshell_express_base_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.identity(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_base_id(ifcopenshell_express_base_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.id(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_express_entity_t* ifcopenshell_entity_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = express::Entity(); + return new ifcopenshell_express_entity_t{ {}, std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_entity_list_t* ifcopenshell_entity_get_inverse(ifcopenshell_express_entity_t* handle, const char* attribute_name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.get_inverse(std::string(attribute_name ? attribute_name : "")); + return new ifcopenshell_express_entity_list_t{ handle->owner, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_select_t* ifcopenshell_select_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = express::Select(); + return new ifcopenshell_express_select_t{ {}, std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_t* ifcopenshell_select_concrete(ifcopenshell_express_select_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.concrete(); + return new ifcopenshell_express_base_t{ handle->owner, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_declared_type_t* ifcopenshell_declared_type_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = express::DeclaredType(); + return new ifcopenshell_express_declared_type_t{ {}, std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_full_buffer_impl_t* ifcopenshell_full_buffer_impl_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::full_buffer_impl(); + return new ifcopenshell_full_buffer_impl_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_full_buffer_impl_t* ifcopenshell_full_buffer_impl_new_with_path(const char* path) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::full_buffer_impl(std::string(path ? path : "")); + return new ifcopenshell_full_buffer_impl_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_full_buffer_impl_size(ifcopenshell_full_buffer_impl_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.size(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_full_buffer_impl_get_u32(ifcopenshell_full_buffer_impl_t* handle, int position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.get_u32(position); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +void ifcopenshell_full_buffer_impl_push_next_page(ifcopenshell_full_buffer_impl_t* handle, const char* page_data) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.push_next_page(std::string(page_data ? page_data : "")); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_full_buffer_impl_drop_pages(ifcopenshell_full_buffer_impl_t* handle, int up_to_position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.drop_pages(up_to_position); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +ifcopenshell_paged_file_impl_t* ifcopenshell_paged_file_impl_new_with_path_page_size_page_capacity(const char* path, int page_size, int page_capacity) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::paged_file_impl(std::string(path ? path : ""), page_size, page_capacity); + return new ifcopenshell_paged_file_impl_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_paged_file_impl_size(ifcopenshell_paged_file_impl_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.size(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_paged_file_impl_get_u32(ifcopenshell_paged_file_impl_t* handle, int position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.get_u32(position); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +void ifcopenshell_paged_file_impl_push_next_page(ifcopenshell_paged_file_impl_t* handle, const char* page_data) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.push_next_page(std::string(page_data ? page_data : "")); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_paged_file_impl_drop_pages(ifcopenshell_paged_file_impl_t* handle, int up_to_position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.drop_pages(up_to_position); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +int ifcopenshell_pushed_sequential_impl_size(ifcopenshell_pushed_sequential_impl_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.size(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_pushed_sequential_impl_get_u32(ifcopenshell_pushed_sequential_impl_t* handle, int position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value.get_u32(position); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +void ifcopenshell_pushed_sequential_impl_push_next_page(ifcopenshell_pushed_sequential_impl_t* handle, const char* page_data) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.push_next_page(std::string(page_data ? page_data : "")); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_pushed_sequential_impl_drop_pages(ifcopenshell_pushed_sequential_impl_t* handle, int up_to_position) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value.drop_pages(up_to_position); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +ifcopenshell_character_encoder_t* ifcopenshell_character_encoder_new_with_input(const char* input) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::character_encoder(std::string(input ? input : "")); + return new ifcopenshell_character_encoder_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_file_t* ifcopenshell_file_new_with_path(const char* path) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = std::make_shared(std::string(path ? path : "")); + return new ifcopenshell_file_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_file_t* ifcopenshell_file_new_with_path_with_filetype(const char* path, ifcopenshell_file_type_t filetype) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = std::make_shared(std::string(path ? path : ""), static_cast(filetype)); + return new ifcopenshell_file_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_file_t* ifcopenshell_file_new_with_path_with_filetype_readonly(const char* path, ifcopenshell_file_type_t filetype, bool readonly) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = std::make_shared(std::string(path ? path : ""), static_cast(filetype), readonly); + return new ifcopenshell_file_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +bool ifcopenshell_file_initialize(ifcopenshell_file_t* handle, const char* path) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->initialize(std::string(path ? path : "")); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +bool ifcopenshell_file_initialize_with_filetype(ifcopenshell_file_t* handle, const char* path, ifcopenshell_file_type_t filetype) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->initialize(std::string(path ? path : ""), static_cast(filetype)); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +bool ifcopenshell_file_initialize_with_filetype_readonly(ifcopenshell_file_t* handle, const char* path, ifcopenshell_file_type_t filetype, bool readonly) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->initialize(std::string(path ? path : ""), static_cast(filetype), readonly); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +void ifcopenshell_file_bypass_type(ifcopenshell_file_t* handle, const char* type_name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->bypass_type(std::string(type_name ? type_name : "")); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +ifcopenshell_file_open_status_t* ifcopenshell_file_good(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->good(); + return new ifcopenshell_file_open_status_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_type(ifcopenshell_file_t* handle, const char* type_name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->instances_by_type(std::string(type_name ? type_name : "")); + return new ifcopenshell_express_base_list_t{ handle->value, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_type_excl_subtypes(ifcopenshell_file_t* handle, const char* type_name) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->instances_by_type_excl_subtypes(std::string(type_name ? type_name : "")); + return new ifcopenshell_express_base_list_t{ handle->value, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_reference(ifcopenshell_file_t* handle, int reference_id) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->instances_by_reference(reference_id); + return new ifcopenshell_express_base_list_t{ handle->value, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_t* ifcopenshell_file_instance_by_id(ifcopenshell_file_t* handle, int instance_id) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->instance_by_id(instance_id); + return new ifcopenshell_express_base_t{ handle->value, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_express_base_t* ifcopenshell_file_instance_by_guid(ifcopenshell_file_t* handle, const char* global_id) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->instance_by_guid(std::string(global_id ? global_id : "")); + return new ifcopenshell_express_base_t{ handle->value, std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_file_get_total_inverses(ifcopenshell_file_t* handle, int instance_id) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->get_total_inverses(instance_id); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_file_fresh_id(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->fresh_id(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +int ifcopenshell_file_get_max_id(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + return handle->value->get_max_id(); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_declaration_t* ifcopenshell_file_ifcroot_type(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value->ifcroot_type(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_declaration_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_file_recalculate_id_counter(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->recalculate_id_counter(); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +ifcopenshell_spf_header_t* ifcopenshell_file_header(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value->header(); + return new ifcopenshell_spf_header_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_schema_definition_t* ifcopenshell_file_schema(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result_ptr = handle->value->schema(); + if (result_ptr == nullptr) { + return nullptr; + } + auto result = *result_ptr; + return new ifcopenshell_schema_definition_t{ std::move(result) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_file_build_inverses(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->build_inverses(); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_file_batch(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->batch(); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_file_unbatch(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->unbatch(); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +void ifcopenshell_file_reset_identity_cache(ifcopenshell_file_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + handle->value->reset_identity_cache(); + return; + } catch (const std::exception& exception) { + set_last_error(exception); + return; + } +} + +ifcopenshell_global_id_t* ifcopenshell_global_id_new() { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::global_id(); + return new ifcopenshell_global_id_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +ifcopenshell_global_id_t* ifcopenshell_global_id_new_with_value(const char* value) { + ifcopenshell_last_error_clear(); + try { + auto constructed_value = ifcopenshell::global_id(std::string(value ? value : "")); + return new ifcopenshell_global_id_t{ std::move(constructed_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +char* ifcopenshell_global_id_formatted(ifcopenshell_global_id_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null handle received"); + } + auto result = handle->value.formatted(); + return duplicate_string(result); + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +int ifcopenshell_declaration_list_size(const ifcopenshell_declaration_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_declaration_t* ifcopenshell_declaration_list_get(const ifcopenshell_declaration_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_declaration_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_declaration_list_free(ifcopenshell_declaration_list_t* handle) { + delete handle; +} + +int ifcopenshell_entity_list_size(const ifcopenshell_entity_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_entity_t* ifcopenshell_entity_list_get(const ifcopenshell_entity_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_entity_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_entity_list_free(ifcopenshell_entity_list_t* handle) { + delete handle; +} + +int ifcopenshell_attribute_list_size(const ifcopenshell_attribute_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_attribute_t* ifcopenshell_attribute_list_get(const ifcopenshell_attribute_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_attribute_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_attribute_list_free(ifcopenshell_attribute_list_t* handle) { + delete handle; +} + +int ifcopenshell_inverse_attribute_list_size(const ifcopenshell_inverse_attribute_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_inverse_attribute_t* ifcopenshell_inverse_attribute_list_get(const ifcopenshell_inverse_attribute_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_inverse_attribute_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_inverse_attribute_list_free(ifcopenshell_inverse_attribute_list_t* handle) { + delete handle; +} + +int ifcopenshell_type_declaration_list_size(const ifcopenshell_type_declaration_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_type_declaration_t* ifcopenshell_type_declaration_list_get(const ifcopenshell_type_declaration_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_type_declaration_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_type_declaration_list_free(ifcopenshell_type_declaration_list_t* handle) { + delete handle; +} + +int ifcopenshell_select_type_list_size(const ifcopenshell_select_type_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_select_type_t* ifcopenshell_select_type_list_get(const ifcopenshell_select_type_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_select_type_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_select_type_list_free(ifcopenshell_select_type_list_t* handle) { + delete handle; +} + +int ifcopenshell_enumeration_type_list_size(const ifcopenshell_enumeration_type_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_enumeration_type_t* ifcopenshell_enumeration_type_list_get(const ifcopenshell_enumeration_type_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_enumeration_type_t{ std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_enumeration_type_list_free(ifcopenshell_enumeration_type_list_t* handle) { + delete handle; +} + +int ifcopenshell_express_entity_list_size(const ifcopenshell_express_entity_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_express_entity_t* ifcopenshell_express_entity_list_get(const ifcopenshell_express_entity_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_express_entity_t{ handle->owner, std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_express_entity_list_free(ifcopenshell_express_entity_list_t* handle) { + delete handle; +} + +int ifcopenshell_express_base_list_size(const ifcopenshell_express_base_list_t* handle) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + return static_cast(handle->value.size()); + } catch (const std::exception& exception) { + set_last_error(exception); + return 0; + } +} + +ifcopenshell_express_base_t* ifcopenshell_express_base_list_get(const ifcopenshell_express_base_list_t* handle, int index) { + ifcopenshell_last_error_clear(); + try { + if (handle == nullptr) { + throw std::runtime_error("Null list handle received"); + } + if (index < 0 || static_cast(index) >= handle->value.size()) { + throw std::out_of_range("List index out of range"); + } + auto item_value = handle->value.at(static_cast(index)); + return new ifcopenshell_express_base_t{ handle->owner, std::move(item_value) }; + } catch (const std::exception& exception) { + set_last_error(exception); + return nullptr; + } +} + +void ifcopenshell_express_base_list_free(ifcopenshell_express_base_list_t* handle) { + delete handle; +} + +void ifcopenshell_exception_free(ifcopenshell_exception_t* handle) { + delete handle; +} + +void ifcopenshell_attribute_out_of_range_exception_free(ifcopenshell_attribute_out_of_range_exception_t* handle) { + delete handle; +} + +void ifcopenshell_invalid_token_exception_free(ifcopenshell_invalid_token_exception_t* handle) { + delete handle; +} + +void ifcopenshell_parameter_type_free(ifcopenshell_parameter_type_t* handle) { + delete handle; +} + +void ifcopenshell_named_type_free(ifcopenshell_named_type_t* handle) { + delete handle; +} + +void ifcopenshell_simple_type_free(ifcopenshell_simple_type_t* handle) { + delete handle; +} + +void ifcopenshell_aggregation_type_free(ifcopenshell_aggregation_type_t* handle) { + delete handle; +} + +void ifcopenshell_declaration_free(ifcopenshell_declaration_t* handle) { + delete handle; +} + +void ifcopenshell_type_declaration_free(ifcopenshell_type_declaration_t* handle) { + delete handle; +} + +void ifcopenshell_select_type_free(ifcopenshell_select_type_t* handle) { + delete handle; +} + +void ifcopenshell_enumeration_type_free(ifcopenshell_enumeration_type_t* handle) { + delete handle; +} + +void ifcopenshell_attribute_free(ifcopenshell_attribute_t* handle) { + delete handle; +} + +void ifcopenshell_inverse_attribute_free(ifcopenshell_inverse_attribute_t* handle) { + delete handle; +} + +void ifcopenshell_entity_free(ifcopenshell_entity_t* handle) { + delete handle; +} + +void ifcopenshell_schema_definition_free(ifcopenshell_schema_definition_t* handle) { + delete handle; +} + +void ifcopenshell_express_base_free(ifcopenshell_express_base_t* handle) { + delete handle; +} + +void ifcopenshell_express_entity_free(ifcopenshell_express_entity_t* handle) { + delete handle; +} + +void ifcopenshell_express_select_free(ifcopenshell_express_select_t* handle) { + delete handle; +} + +void ifcopenshell_express_declared_type_free(ifcopenshell_express_declared_type_t* handle) { + delete handle; +} + +void ifcopenshell_full_buffer_impl_free(ifcopenshell_full_buffer_impl_t* handle) { + delete handle; +} + +void ifcopenshell_paged_file_impl_free(ifcopenshell_paged_file_impl_t* handle) { + delete handle; +} + +void ifcopenshell_pushed_sequential_impl_free(ifcopenshell_pushed_sequential_impl_t* handle) { + delete handle; +} + +void ifcopenshell_character_encoder_free(ifcopenshell_character_encoder_t* handle) { + delete handle; +} + +void ifcopenshell_file_open_status_free(ifcopenshell_file_open_status_t* handle) { + delete handle; +} + +void ifcopenshell_spf_header_free(ifcopenshell_spf_header_t* handle) { + delete handle; +} + +void ifcopenshell_file_free(ifcopenshell_file_t* handle) { + delete handle; +} + +void ifcopenshell_global_id_free(ifcopenshell_global_id_t* handle) { + delete handle; +} + +} diff --git a/src/wrappergen/generated/ifcopenshell_experimental_c_api.h b/src/wrappergen/generated/ifcopenshell_experimental_c_api.h new file mode 100644 index 0000000000..b30e6372d7 --- /dev/null +++ b/src/wrappergen/generated/ifcopenshell_experimental_c_api.h @@ -0,0 +1,241 @@ +#ifndef IFCOPENSHELL_EXPERIMENTAL_C_API_H +#define IFCOPENSHELL_EXPERIMENTAL_C_API_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ifcopenshell_exception_t ifcopenshell_exception_t; +typedef struct ifcopenshell_attribute_out_of_range_exception_t ifcopenshell_attribute_out_of_range_exception_t; +typedef struct ifcopenshell_invalid_token_exception_t ifcopenshell_invalid_token_exception_t; +typedef struct ifcopenshell_parameter_type_t ifcopenshell_parameter_type_t; +typedef struct ifcopenshell_named_type_t ifcopenshell_named_type_t; +typedef struct ifcopenshell_simple_type_t ifcopenshell_simple_type_t; +typedef struct ifcopenshell_aggregation_type_t ifcopenshell_aggregation_type_t; +typedef struct ifcopenshell_declaration_t ifcopenshell_declaration_t; +typedef struct ifcopenshell_type_declaration_t ifcopenshell_type_declaration_t; +typedef struct ifcopenshell_select_type_t ifcopenshell_select_type_t; +typedef struct ifcopenshell_enumeration_type_t ifcopenshell_enumeration_type_t; +typedef struct ifcopenshell_attribute_t ifcopenshell_attribute_t; +typedef struct ifcopenshell_inverse_attribute_t ifcopenshell_inverse_attribute_t; +typedef struct ifcopenshell_entity_t ifcopenshell_entity_t; +typedef struct ifcopenshell_schema_definition_t ifcopenshell_schema_definition_t; +typedef struct ifcopenshell_express_base_t ifcopenshell_express_base_t; +typedef struct ifcopenshell_express_entity_t ifcopenshell_express_entity_t; +typedef struct ifcopenshell_express_select_t ifcopenshell_express_select_t; +typedef struct ifcopenshell_express_declared_type_t ifcopenshell_express_declared_type_t; +typedef struct ifcopenshell_full_buffer_impl_t ifcopenshell_full_buffer_impl_t; +typedef struct ifcopenshell_paged_file_impl_t ifcopenshell_paged_file_impl_t; +typedef struct ifcopenshell_pushed_sequential_impl_t ifcopenshell_pushed_sequential_impl_t; +typedef struct ifcopenshell_character_encoder_t ifcopenshell_character_encoder_t; +typedef struct ifcopenshell_file_open_status_t ifcopenshell_file_open_status_t; +typedef struct ifcopenshell_spf_header_t ifcopenshell_spf_header_t; +typedef struct ifcopenshell_file_t ifcopenshell_file_t; +typedef struct ifcopenshell_global_id_t ifcopenshell_global_id_t; + +typedef struct ifcopenshell_declaration_list_t ifcopenshell_declaration_list_t; +typedef struct ifcopenshell_entity_list_t ifcopenshell_entity_list_t; +typedef struct ifcopenshell_attribute_list_t ifcopenshell_attribute_list_t; +typedef struct ifcopenshell_inverse_attribute_list_t ifcopenshell_inverse_attribute_list_t; +typedef struct ifcopenshell_type_declaration_list_t ifcopenshell_type_declaration_list_t; +typedef struct ifcopenshell_select_type_list_t ifcopenshell_select_type_list_t; +typedef struct ifcopenshell_enumeration_type_list_t ifcopenshell_enumeration_type_list_t; +typedef struct ifcopenshell_express_entity_list_t ifcopenshell_express_entity_list_t; +typedef struct ifcopenshell_express_base_list_t ifcopenshell_express_base_list_t; + +typedef enum ifcopenshell_file_type_t { + IFCOPENSHELL_FILE_TYPE_T_FT_IFCSPF = 0, + IFCOPENSHELL_FILE_TYPE_T_FT_IFCXML = 1, + IFCOPENSHELL_FILE_TYPE_T_FT_IFCZIP = 2, + IFCOPENSHELL_FILE_TYPE_T_FT_ROCKSDB = 3, + IFCOPENSHELL_FILE_TYPE_T_FT_UNKNOWN = 4, + IFCOPENSHELL_FILE_TYPE_T_FT_AUTODETECT = 5, +} ifcopenshell_file_type_t; + +const char* ifcopenshell_last_error_message(void); +void ifcopenshell_last_error_clear(void); +void ifcopenshell_string_free(char* value); + +ifcopenshell_exception_t* ifcopenshell_exception_new_with_message(const char* message); +ifcopenshell_attribute_out_of_range_exception_t* ifcopenshell_attribute_out_of_range_exception_new_with_message(const char* message); +ifcopenshell_invalid_token_exception_t* ifcopenshell_invalid_token_exception_new_with_token_start_token_string_expected_type(int token_start, const char* token_string, const char* expected_type); +ifcopenshell_named_type_t* ifcopenshell_parameter_type_as_named_type(ifcopenshell_parameter_type_t* handle); +ifcopenshell_simple_type_t* ifcopenshell_parameter_type_as_simple_type(ifcopenshell_parameter_type_t* handle); +ifcopenshell_aggregation_type_t* ifcopenshell_parameter_type_as_aggregation_type(ifcopenshell_parameter_type_t* handle); +bool ifcopenshell_parameter_type_is(ifcopenshell_parameter_type_t* handle, const char* arg0); +ifcopenshell_declaration_t* ifcopenshell_named_type_declared_type(ifcopenshell_named_type_t* handle); +ifcopenshell_named_type_t* ifcopenshell_named_type_as_named_type(ifcopenshell_named_type_t* handle); +bool ifcopenshell_named_type_is(ifcopenshell_named_type_t* handle, const char* name); +ifcopenshell_simple_type_t* ifcopenshell_simple_type_as_simple_type(ifcopenshell_simple_type_t* handle); +int ifcopenshell_aggregation_type_bound1(ifcopenshell_aggregation_type_t* handle); +int ifcopenshell_aggregation_type_bound2(ifcopenshell_aggregation_type_t* handle); +ifcopenshell_parameter_type_t* ifcopenshell_aggregation_type_type_of_element(ifcopenshell_aggregation_type_t* handle); +ifcopenshell_aggregation_type_t* ifcopenshell_aggregation_type_as_aggregation_type(ifcopenshell_aggregation_type_t* handle); +ifcopenshell_declaration_t* ifcopenshell_declaration_new_with_name_index_in_schema(const char* name, int index_in_schema); +char* ifcopenshell_declaration_name(ifcopenshell_declaration_t* handle); +char* ifcopenshell_declaration_name_uc(ifcopenshell_declaration_t* handle); +ifcopenshell_type_declaration_t* ifcopenshell_declaration_as_type_declaration(ifcopenshell_declaration_t* handle); +ifcopenshell_select_type_t* ifcopenshell_declaration_as_select_type(ifcopenshell_declaration_t* handle); +ifcopenshell_enumeration_type_t* ifcopenshell_declaration_as_enumeration_type(ifcopenshell_declaration_t* handle); +ifcopenshell_entity_t* ifcopenshell_declaration_as_entity(ifcopenshell_declaration_t* handle); +bool ifcopenshell_declaration_is(ifcopenshell_declaration_t* handle, const char* name); +int ifcopenshell_declaration_index_in_schema(ifcopenshell_declaration_t* handle); +int ifcopenshell_declaration_type(ifcopenshell_declaration_t* handle); +ifcopenshell_schema_definition_t* ifcopenshell_declaration_schema(ifcopenshell_declaration_t* handle); +ifcopenshell_parameter_type_t* ifcopenshell_type_declaration_declared_type(ifcopenshell_type_declaration_t* handle); +ifcopenshell_type_declaration_t* ifcopenshell_type_declaration_as_type_declaration(ifcopenshell_type_declaration_t* handle); +ifcopenshell_declaration_list_t* ifcopenshell_select_type_select_list(ifcopenshell_select_type_t* handle); +ifcopenshell_select_type_t* ifcopenshell_select_type_as_select_type(ifcopenshell_select_type_t* handle); +int ifcopenshell_enumeration_type_lookup_enum_offset(ifcopenshell_enumeration_type_t* handle, const char* value_name); +ifcopenshell_enumeration_type_t* ifcopenshell_enumeration_type_as_enumeration_type(ifcopenshell_enumeration_type_t* handle); +char* ifcopenshell_attribute_name(ifcopenshell_attribute_t* handle); +ifcopenshell_parameter_type_t* ifcopenshell_attribute_type_of_attribute(ifcopenshell_attribute_t* handle); +bool ifcopenshell_attribute_optional(ifcopenshell_attribute_t* handle); +char* ifcopenshell_inverse_attribute_name(ifcopenshell_inverse_attribute_t* handle); +int ifcopenshell_inverse_attribute_bound1(ifcopenshell_inverse_attribute_t* handle); +int ifcopenshell_inverse_attribute_bound2(ifcopenshell_inverse_attribute_t* handle); +ifcopenshell_entity_t* ifcopenshell_inverse_attribute_entity_reference(ifcopenshell_inverse_attribute_t* handle); +ifcopenshell_attribute_t* ifcopenshell_inverse_attribute_attribute_reference(ifcopenshell_inverse_attribute_t* handle); +bool ifcopenshell_entity_is_abstract(ifcopenshell_entity_t* handle); +ifcopenshell_entity_list_t* ifcopenshell_entity_subtypes(ifcopenshell_entity_t* handle); +ifcopenshell_attribute_list_t* ifcopenshell_entity_attributes(ifcopenshell_entity_t* handle); +ifcopenshell_attribute_list_t* ifcopenshell_entity_all_attributes(ifcopenshell_entity_t* handle); +ifcopenshell_inverse_attribute_list_t* ifcopenshell_entity_all_inverse_attributes(ifcopenshell_entity_t* handle); +ifcopenshell_attribute_t* ifcopenshell_entity_attribute_by_index(ifcopenshell_entity_t* handle, int index); +int ifcopenshell_entity_attribute_count(ifcopenshell_entity_t* handle); +ifcopenshell_entity_t* ifcopenshell_entity_supertype(ifcopenshell_entity_t* handle); +ifcopenshell_entity_t* ifcopenshell_entity_as_entity(ifcopenshell_entity_t* handle); +ifcopenshell_declaration_t* ifcopenshell_schema_definition_declaration_by_name_with_name(ifcopenshell_schema_definition_t* handle, const char* name); +ifcopenshell_declaration_t* ifcopenshell_schema_definition_declaration_by_name_with_declaration_index(ifcopenshell_schema_definition_t* handle, int declaration_index); +ifcopenshell_declaration_list_t* ifcopenshell_schema_definition_declarations(ifcopenshell_schema_definition_t* handle); +ifcopenshell_type_declaration_list_t* ifcopenshell_schema_definition_type_declarations(ifcopenshell_schema_definition_t* handle); +ifcopenshell_select_type_list_t* ifcopenshell_schema_definition_select_types(ifcopenshell_schema_definition_t* handle); +ifcopenshell_enumeration_type_list_t* ifcopenshell_schema_definition_enumeration_types(ifcopenshell_schema_definition_t* handle); +ifcopenshell_entity_list_t* ifcopenshell_schema_definition_entities(ifcopenshell_schema_definition_t* handle); +char* ifcopenshell_schema_definition_name(ifcopenshell_schema_definition_t* handle); +ifcopenshell_express_base_t* ifcopenshell_base_new(); +ifcopenshell_declaration_t* ifcopenshell_base_declaration(ifcopenshell_express_base_t* handle); +void ifcopenshell_base_unset_attribute_value(ifcopenshell_express_base_t* handle, int attribute_index); +int ifcopenshell_base_identity(ifcopenshell_express_base_t* handle); +int ifcopenshell_base_id(ifcopenshell_express_base_t* handle); +ifcopenshell_express_entity_t* ifcopenshell_entity_new(); +ifcopenshell_express_entity_list_t* ifcopenshell_entity_get_inverse(ifcopenshell_express_entity_t* handle, const char* attribute_name); +ifcopenshell_express_select_t* ifcopenshell_select_new(); +ifcopenshell_express_base_t* ifcopenshell_select_concrete(ifcopenshell_express_select_t* handle); +ifcopenshell_express_declared_type_t* ifcopenshell_declared_type_new(); +ifcopenshell_full_buffer_impl_t* ifcopenshell_full_buffer_impl_new(); +ifcopenshell_full_buffer_impl_t* ifcopenshell_full_buffer_impl_new_with_path(const char* path); +int ifcopenshell_full_buffer_impl_size(ifcopenshell_full_buffer_impl_t* handle); +int ifcopenshell_full_buffer_impl_get_u32(ifcopenshell_full_buffer_impl_t* handle, int position); +void ifcopenshell_full_buffer_impl_push_next_page(ifcopenshell_full_buffer_impl_t* handle, const char* page_data); +void ifcopenshell_full_buffer_impl_drop_pages(ifcopenshell_full_buffer_impl_t* handle, int up_to_position); +ifcopenshell_paged_file_impl_t* ifcopenshell_paged_file_impl_new_with_path_page_size_page_capacity(const char* path, int page_size, int page_capacity); +int ifcopenshell_paged_file_impl_size(ifcopenshell_paged_file_impl_t* handle); +int ifcopenshell_paged_file_impl_get_u32(ifcopenshell_paged_file_impl_t* handle, int position); +void ifcopenshell_paged_file_impl_push_next_page(ifcopenshell_paged_file_impl_t* handle, const char* page_data); +void ifcopenshell_paged_file_impl_drop_pages(ifcopenshell_paged_file_impl_t* handle, int up_to_position); +int ifcopenshell_pushed_sequential_impl_size(ifcopenshell_pushed_sequential_impl_t* handle); +int ifcopenshell_pushed_sequential_impl_get_u32(ifcopenshell_pushed_sequential_impl_t* handle, int position); +void ifcopenshell_pushed_sequential_impl_push_next_page(ifcopenshell_pushed_sequential_impl_t* handle, const char* page_data); +void ifcopenshell_pushed_sequential_impl_drop_pages(ifcopenshell_pushed_sequential_impl_t* handle, int up_to_position); +ifcopenshell_character_encoder_t* ifcopenshell_character_encoder_new_with_input(const char* input); +ifcopenshell_file_t* ifcopenshell_file_new_with_path(const char* path); +ifcopenshell_file_t* ifcopenshell_file_new_with_path_with_filetype(const char* path, ifcopenshell_file_type_t filetype); +ifcopenshell_file_t* ifcopenshell_file_new_with_path_with_filetype_readonly(const char* path, ifcopenshell_file_type_t filetype, bool readonly); +bool ifcopenshell_file_initialize(ifcopenshell_file_t* handle, const char* path); +bool ifcopenshell_file_initialize_with_filetype(ifcopenshell_file_t* handle, const char* path, ifcopenshell_file_type_t filetype); +bool ifcopenshell_file_initialize_with_filetype_readonly(ifcopenshell_file_t* handle, const char* path, ifcopenshell_file_type_t filetype, bool readonly); +void ifcopenshell_file_bypass_type(ifcopenshell_file_t* handle, const char* type_name); +ifcopenshell_file_open_status_t* ifcopenshell_file_good(ifcopenshell_file_t* handle); +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_type(ifcopenshell_file_t* handle, const char* type_name); +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_type_excl_subtypes(ifcopenshell_file_t* handle, const char* type_name); +ifcopenshell_express_base_list_t* ifcopenshell_file_instances_by_reference(ifcopenshell_file_t* handle, int reference_id); +ifcopenshell_express_base_t* ifcopenshell_file_instance_by_id(ifcopenshell_file_t* handle, int instance_id); +ifcopenshell_express_base_t* ifcopenshell_file_instance_by_guid(ifcopenshell_file_t* handle, const char* global_id); +int ifcopenshell_file_get_total_inverses(ifcopenshell_file_t* handle, int instance_id); +int ifcopenshell_file_fresh_id(ifcopenshell_file_t* handle); +int ifcopenshell_file_get_max_id(ifcopenshell_file_t* handle); +ifcopenshell_declaration_t* ifcopenshell_file_ifcroot_type(ifcopenshell_file_t* handle); +void ifcopenshell_file_recalculate_id_counter(ifcopenshell_file_t* handle); +ifcopenshell_spf_header_t* ifcopenshell_file_header(ifcopenshell_file_t* handle); +ifcopenshell_schema_definition_t* ifcopenshell_file_schema(ifcopenshell_file_t* handle); +void ifcopenshell_file_build_inverses(ifcopenshell_file_t* handle); +void ifcopenshell_file_batch(ifcopenshell_file_t* handle); +void ifcopenshell_file_unbatch(ifcopenshell_file_t* handle); +void ifcopenshell_file_reset_identity_cache(ifcopenshell_file_t* handle); +ifcopenshell_global_id_t* ifcopenshell_global_id_new(); +ifcopenshell_global_id_t* ifcopenshell_global_id_new_with_value(const char* value); +char* ifcopenshell_global_id_formatted(ifcopenshell_global_id_t* handle); + +int ifcopenshell_declaration_list_size(const ifcopenshell_declaration_list_t* handle); +ifcopenshell_declaration_t* ifcopenshell_declaration_list_get(const ifcopenshell_declaration_list_t* handle, int index); +void ifcopenshell_declaration_list_free(ifcopenshell_declaration_list_t* handle); + +int ifcopenshell_entity_list_size(const ifcopenshell_entity_list_t* handle); +ifcopenshell_entity_t* ifcopenshell_entity_list_get(const ifcopenshell_entity_list_t* handle, int index); +void ifcopenshell_entity_list_free(ifcopenshell_entity_list_t* handle); + +int ifcopenshell_attribute_list_size(const ifcopenshell_attribute_list_t* handle); +ifcopenshell_attribute_t* ifcopenshell_attribute_list_get(const ifcopenshell_attribute_list_t* handle, int index); +void ifcopenshell_attribute_list_free(ifcopenshell_attribute_list_t* handle); + +int ifcopenshell_inverse_attribute_list_size(const ifcopenshell_inverse_attribute_list_t* handle); +ifcopenshell_inverse_attribute_t* ifcopenshell_inverse_attribute_list_get(const ifcopenshell_inverse_attribute_list_t* handle, int index); +void ifcopenshell_inverse_attribute_list_free(ifcopenshell_inverse_attribute_list_t* handle); + +int ifcopenshell_type_declaration_list_size(const ifcopenshell_type_declaration_list_t* handle); +ifcopenshell_type_declaration_t* ifcopenshell_type_declaration_list_get(const ifcopenshell_type_declaration_list_t* handle, int index); +void ifcopenshell_type_declaration_list_free(ifcopenshell_type_declaration_list_t* handle); + +int ifcopenshell_select_type_list_size(const ifcopenshell_select_type_list_t* handle); +ifcopenshell_select_type_t* ifcopenshell_select_type_list_get(const ifcopenshell_select_type_list_t* handle, int index); +void ifcopenshell_select_type_list_free(ifcopenshell_select_type_list_t* handle); + +int ifcopenshell_enumeration_type_list_size(const ifcopenshell_enumeration_type_list_t* handle); +ifcopenshell_enumeration_type_t* ifcopenshell_enumeration_type_list_get(const ifcopenshell_enumeration_type_list_t* handle, int index); +void ifcopenshell_enumeration_type_list_free(ifcopenshell_enumeration_type_list_t* handle); + +int ifcopenshell_express_entity_list_size(const ifcopenshell_express_entity_list_t* handle); +ifcopenshell_express_entity_t* ifcopenshell_express_entity_list_get(const ifcopenshell_express_entity_list_t* handle, int index); +void ifcopenshell_express_entity_list_free(ifcopenshell_express_entity_list_t* handle); + +int ifcopenshell_express_base_list_size(const ifcopenshell_express_base_list_t* handle); +ifcopenshell_express_base_t* ifcopenshell_express_base_list_get(const ifcopenshell_express_base_list_t* handle, int index); +void ifcopenshell_express_base_list_free(ifcopenshell_express_base_list_t* handle); + +void ifcopenshell_exception_free(ifcopenshell_exception_t* handle); +void ifcopenshell_attribute_out_of_range_exception_free(ifcopenshell_attribute_out_of_range_exception_t* handle); +void ifcopenshell_invalid_token_exception_free(ifcopenshell_invalid_token_exception_t* handle); +void ifcopenshell_parameter_type_free(ifcopenshell_parameter_type_t* handle); +void ifcopenshell_named_type_free(ifcopenshell_named_type_t* handle); +void ifcopenshell_simple_type_free(ifcopenshell_simple_type_t* handle); +void ifcopenshell_aggregation_type_free(ifcopenshell_aggregation_type_t* handle); +void ifcopenshell_declaration_free(ifcopenshell_declaration_t* handle); +void ifcopenshell_type_declaration_free(ifcopenshell_type_declaration_t* handle); +void ifcopenshell_select_type_free(ifcopenshell_select_type_t* handle); +void ifcopenshell_enumeration_type_free(ifcopenshell_enumeration_type_t* handle); +void ifcopenshell_attribute_free(ifcopenshell_attribute_t* handle); +void ifcopenshell_inverse_attribute_free(ifcopenshell_inverse_attribute_t* handle); +void ifcopenshell_entity_free(ifcopenshell_entity_t* handle); +void ifcopenshell_schema_definition_free(ifcopenshell_schema_definition_t* handle); +void ifcopenshell_express_base_free(ifcopenshell_express_base_t* handle); +void ifcopenshell_express_entity_free(ifcopenshell_express_entity_t* handle); +void ifcopenshell_express_select_free(ifcopenshell_express_select_t* handle); +void ifcopenshell_express_declared_type_free(ifcopenshell_express_declared_type_t* handle); +void ifcopenshell_full_buffer_impl_free(ifcopenshell_full_buffer_impl_t* handle); +void ifcopenshell_paged_file_impl_free(ifcopenshell_paged_file_impl_t* handle); +void ifcopenshell_pushed_sequential_impl_free(ifcopenshell_pushed_sequential_impl_t* handle); +void ifcopenshell_character_encoder_free(ifcopenshell_character_encoder_t* handle); +void ifcopenshell_file_open_status_free(ifcopenshell_file_open_status_t* handle); +void ifcopenshell_spf_header_free(ifcopenshell_spf_header_t* handle); +void ifcopenshell_file_free(ifcopenshell_file_t* handle); +void ifcopenshell_global_id_free(ifcopenshell_global_id_t* handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/wrappergen/model.py b/src/wrappergen/model.py new file mode 100644 index 0000000000..458a963bfd --- /dev/null +++ b/src/wrappergen/model.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +from dataclasses import dataclass, field + + +@dataclass(slots=True) +class ParameterModel: + name: str + cpp_name: str + cpp_type: str + adapter: str + has_default: bool = False + default_cpp_value: str | None = None + default_python_value: str | None = None + + +@dataclass(slots=True) +class CallableModel: + kind: str + owner_cpp_name: str + owner_py_name: str + cpp_name: str + py_name: str + c_name: str + return_cpp_type: str + return_adapter: str + parameters: list[ParameterModel] = field(default_factory=list) + + @property + def minimum_arity(self) -> int: + defaults = 0 + for parameter in reversed(self.parameters): + if not parameter.has_default: + break + defaults += 1 + return len(self.parameters) - defaults + + +@dataclass(slots=True) +class EnumValueModel: + name: str + c_name: str + value: int + + +@dataclass(slots=True) +class EnumModel: + cpp_name: str + py_name: str + c_name: str + values: list[EnumValueModel] + + +@dataclass(slots=True) +class ClassModel: + cpp_name: str + py_name: str + handle_kind: str + owner_cpp_name: str | None = None + owner_py_name: str | None = None + callables: list[CallableModel] = field(default_factory=list) + + +@dataclass(slots=True) +class ModuleModel: + module_name: str + c_prefix: str + api_header_name: str + api_implementation_name: str + extension_source_name: str + python_source_name: str + source_headers: list[str] + classes: list[ClassModel] + enums: list[EnumModel]