cgcpp 1.8.2__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cgcpp/__init__.py ADDED
@@ -0,0 +1,113 @@
1
+ """
2
+ (c) Andriy Babak 2021-2025
3
+
4
+ date: 31/05/2021
5
+ modified: 03/04/2025 12:10:58
6
+
7
+ Author: Andriy Babak
8
+ e-mail: ababak@gmail.com
9
+ ------------------------------
10
+ description: CG C++ Support module
11
+ Containerized builds and runtime loading
12
+ ------------------------------
13
+ """
14
+
15
+ import importlib.metadata
16
+ import importlib.util
17
+ import inspect
18
+ import os
19
+ import platform
20
+ import sys
21
+ from pathlib import Path
22
+
23
+ __version__ = importlib.metadata.version("cgcpp")
24
+ __copyright__ = "(c) Andriy Babak 2021-2025"
25
+
26
+ from . import build
27
+
28
+ lib_loader_name = "lib_loader"
29
+ lib_suffix = f"_python{sys.version_info.major}{sys.version_info.minor}"
30
+ lib_loader_path = Path(__file__).with_name(f"{lib_loader_name}{lib_suffix}.pyd")
31
+
32
+ spec = importlib.util.spec_from_file_location(lib_loader_name, lib_loader_path)
33
+ lib_loader = importlib.util.module_from_spec(spec)
34
+ spec.loader.exec_module(lib_loader)
35
+
36
+
37
+ def get_library_path(lib_path, extra_frames=0):
38
+ """
39
+ Try to guess a full library path
40
+ """
41
+ lib_path = Path(lib_path)
42
+ lib_dir = lib_path.parent
43
+ lib_name = os.path.basename(lib_path)
44
+ lib_name, lib_ext = os.path.splitext(lib_path.name)
45
+ local_platform = platform.system().lower()
46
+ if local_platform == "windows":
47
+ lib_ext = ".dll"
48
+ elif local_platform == "linux":
49
+ lib_ext = ".so"
50
+ else:
51
+ raise EnvironmentError(f"Unsupported platform: {local_platform}")
52
+ if not os.path.dirname(lib_path):
53
+ # get call stack frames
54
+ frames = inspect.stack(0)
55
+ frame = 1 + extra_frames
56
+ # should be the third frame
57
+ # 0: this function
58
+ # 1: this module"s "call" function
59
+ # 2: the caller
60
+ if len(frames) > frame:
61
+ path = frames[frame][1]
62
+ if path:
63
+ lib_dir = Path(path).parent
64
+ full_lib_path = lib_dir.absolute() / f"{lib_name}{lib_ext}"
65
+ variants = [f"{lib_name}{lib_ext}", f"{lib_name}{lib_suffix}{lib_ext}"]
66
+ # Try to guess the host application
67
+ try:
68
+ from maya import cmds
69
+ except ImportError:
70
+ pass
71
+ else:
72
+ # The host application is Maya
73
+ maya_version = cmds.about(v=True)
74
+ maya_suffix = f"_maya{maya_version}"
75
+ variants.append(f"{lib_name}{maya_suffix}{lib_ext}")
76
+ variants.append(f"{lib_name}{lib_suffix}{maya_suffix}{lib_ext}")
77
+ try:
78
+ import hou
79
+ from hou import nodes
80
+ except ImportError:
81
+ pass
82
+ else:
83
+ # The host application is Houdini
84
+ houdini_version = os.path.splitext(hou.applicationVersionString())[0]
85
+ houdini_suffix = f"_houdini{houdini_version}"
86
+ variants.append(f"{lib_name}{houdini_suffix}{lib_ext}")
87
+ variants.append(f"{lib_name}{lib_suffix}{houdini_suffix}{lib_ext}")
88
+ for name in variants:
89
+ full_lib_path = lib_dir.absolute() / name
90
+ if full_lib_path.is_file():
91
+ return full_lib_path
92
+ raise AttributeError(
93
+ f'Library not found: "{lib_dir.absolute().with_name(lib_name + lib_ext)}"'
94
+ )
95
+
96
+
97
+ def call(*args, **kwargs):
98
+ """
99
+ Call an external function from dynamically loaded library
100
+ Arguments:
101
+ lib (str) - full library path ("/some/lib/lib.so") or library name ("lib")
102
+ func (str) - function name
103
+ All the arguments get passed to an exported function from the library
104
+ Usage:
105
+ ret = cpp.call("some argument", some_named_argument=42, lib="/lib/path.so", func="custom")
106
+ """
107
+ lib_path = kwargs.get("lib")
108
+ func_name = kwargs.get("func")
109
+ if not lib_path or not func_name:
110
+ raise AttributeError('Invalid usage. Expected arguments: "lib", "func"')
111
+ modified_kwargs = dict(kwargs)
112
+ modified_kwargs["lib"] = get_library_path(lib_path, extra_frames=1).as_posix()
113
+ return lib_loader.call(*args, **modified_kwargs)
cgcpp/__main__.py ADDED
@@ -0,0 +1,69 @@
1
+ """
2
+ (c) Andriy Babak 2021-2024
3
+
4
+ date: 01/06/2021
5
+ modified: 30/01/2025 14:12:22
6
+
7
+ Author: Andriy Babak
8
+ e-mail: ababak@gmail.com
9
+ ------------------------------
10
+ description: CG C++ Support module
11
+ ------------------------------
12
+ """
13
+
14
+ import argparse
15
+ import os
16
+ import sys
17
+
18
+ from . import __copyright__, __version__, build
19
+
20
+
21
+ def main():
22
+ parser = argparse.ArgumentParser(
23
+ description="C++ module builder v{}".format(__version__),
24
+ epilog=__copyright__,
25
+ prog="python -m cgcpp",
26
+ )
27
+ parser.add_argument(
28
+ "source", type=str, help="directory containing CMakeLists.txt to build"
29
+ )
30
+ parser.add_argument("--out", help="output directory")
31
+ parser.add_argument("--build", help="build directory")
32
+ maya_default_directory = "C:/Program Files/Autodesk"
33
+ parser.add_argument(
34
+ "--maya",
35
+ help='Autodesk directory with Maya installations. Default: "{}".'.format(
36
+ maya_default_directory
37
+ ),
38
+ nargs="?",
39
+ const=maya_default_directory,
40
+ )
41
+ sidefx_default_directory = "C:/Program Files/Side Effects Software"
42
+ parser.add_argument(
43
+ "--houdini",
44
+ help='SideFX directory with Houdini installations. Default: "{}".'.format(
45
+ sidefx_default_directory
46
+ ),
47
+ nargs="?",
48
+ const=sidefx_default_directory,
49
+ )
50
+ args, unknownargs = parser.parse_known_args()
51
+ source_dir = os.path.abspath(args.source).replace("\\", "/")
52
+ build_dir = args.build and os.path.abspath(args.build).replace("\\", "/")
53
+ out_dir = os.path.abspath(args.out or source_dir).replace("\\", "/")
54
+ if not os.path.isdir(args.source):
55
+ print('[ERROR] Directory does not exist: "{}"'.format(source_dir))
56
+ sys.exit(1)
57
+ result = build.build(
58
+ source_dir=source_dir,
59
+ destination_dir=out_dir,
60
+ build_dir=build_dir,
61
+ maya_dir=args.maya,
62
+ houdini_dir=args.houdini,
63
+ )
64
+ if not result:
65
+ sys.exit(result)
66
+
67
+
68
+ if __name__ == "__main__":
69
+ main()
cgcpp/build.py ADDED
@@ -0,0 +1,74 @@
1
+ """
2
+ (c) Andriy Babak 2021-2024
3
+
4
+ date: 03/06/2021
5
+ modified: 30/05/2024 10:40:26
6
+
7
+ Author: Andriy Babak
8
+ e-mail: ababak@gmail.com
9
+ ------------------------------
10
+ description: CG C++ Support module
11
+ ------------------------------
12
+ """
13
+
14
+ import os
15
+ import subprocess
16
+
17
+ from . import __version__
18
+
19
+ DOCKER_APP = "docker"
20
+ DOCKER_IMAGE = "ababak/cgcpp:" + ".".join(__version__.split(".")[:2])
21
+
22
+
23
+ def build(
24
+ source_dir,
25
+ destination_dir=None,
26
+ build_dir=None,
27
+ maya_dir=None,
28
+ houdini_dir=None,
29
+ ):
30
+ """Run docker image to build source directory."""
31
+ source_dir = os.path.abspath(source_dir).replace("\\", "/")
32
+ destination_dir = os.path.abspath(destination_dir or source_dir).replace("\\", "/")
33
+ try:
34
+ out = subprocess.check_output([DOCKER_APP, "images", "-q", DOCKER_IMAGE])
35
+ except OSError:
36
+ print("[ERROR] Docker not installed")
37
+ return 2
38
+ if not out:
39
+ print("[ERROR] Docker image is not available: {}".format(DOCKER_IMAGE))
40
+ print("Please reinstall cgcpp to rebuild it")
41
+ return 3
42
+ print('Source: "{}"'.format(source_dir))
43
+ print('Build: "{}"'.format(build_dir))
44
+ print('Output: "{}"'.format(destination_dir))
45
+ docker_args = [
46
+ DOCKER_APP,
47
+ "run",
48
+ "--rm",
49
+ "-v",
50
+ "{}:c:/source:ro".format(os.path.abspath(source_dir)),
51
+ "-v",
52
+ "{}:c:/out".format(os.path.abspath(destination_dir)),
53
+ ]
54
+ if build_dir:
55
+ docker_args += ["-v", "{}:c:/build".format(os.path.abspath(build_dir))]
56
+ if maya_dir:
57
+ maya_dir = os.path.abspath(maya_dir).replace("\\", "/")
58
+ if not os.path.isdir(maya_dir):
59
+ print(
60
+ '[ERROR] Autodesk Maya directory does not exist: "{}"'.format(maya_dir)
61
+ )
62
+ return 1
63
+ docker_args += ["-v", maya_dir + ":c:/autodesk:ro"]
64
+ print('Autodesk Maya search directory: "{}"'.format(maya_dir))
65
+ if houdini_dir:
66
+ houdini_dir = os.path.abspath(houdini_dir).replace("\\", "/")
67
+ if not os.path.isdir(houdini_dir):
68
+ print('[ERROR] SideFX directory does not exist: "{}"'.format(houdini_dir))
69
+ return 1
70
+ docker_args += ["-v", houdini_dir + ":c:/sidefx:ro"]
71
+ print('SideFX search directory: "{}"'.format(houdini_dir))
72
+ docker_args.append(DOCKER_IMAGE)
73
+ subprocess.check_call(docker_args)
74
+ return 0
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: cgcpp
3
+ Version: 1.8.2
4
+ Summary: CG C++ Support module
5
+ Author-email: Andriy Babak <ababak@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/ababak/cgcpp
8
+ Project-URL: Repository, https://github.com/ababak/cgcpp.git
9
+ Description-Content-Type: text/markdown
10
+
11
+ [![Docker Image CI](https://github.com/ababak/cgcpp/actions/workflows/docker-image.yml/badge.svg)](https://github.com/ababak/cgcpp/actions/workflows/docker-image.yml)
12
+
13
+ # Computer Graphics C++ (cgcpp)
14
+ A universal C++ solution for common needs in computer graphics software.
15
+
16
+ ### Supported Environments
17
+ - **Python & Boost Versions** (Windows):
18
+ - Python 3.9, Boost 1.76.0
19
+ - Python 3.10, Boost 1.80.0
20
+ - Python 3.11, Boost 1.82.0
21
+ - Python 3.12, Boost 1.85.0
22
+ - **Autodesk Maya** (Windows):
23
+ - Maya 2023: Python 3.9, Boost 1.76.0
24
+ - Maya 2024: Python 3.10, Boost 1.80.0
25
+ - Maya 2025: Python 3.11, Boost 1.82.0
26
+ - Maya 2026: Python 3.11, Boost 1.85.0
27
+ - **SideFX Houdini** (Windows):
28
+ - Houdini 19.5: Python 3.9, Boost 1.76.0
29
+ - Houdini 20.0: Python 3.10, Boost 1.80.0
30
+ - Houdini 20.5: Python 3.11, Boost 1.82.0
31
+
32
+ Support for additional platforms and DCC applications may be added in the future.
33
+
34
+ ### Features
35
+ - **Isolated builds** inside a Docker container for a predictable environment
36
+ - **Python-C++ integration** to call C++ functions from Python
37
+ - **Dynamic library reloading** (updates libraries on each new call)
38
+ - **Python exception handling** from C++
39
+
40
+ ## Installation
41
+ Install in your Windows Python virtual environment:
42
+
43
+ python -m pip install git+https://github.com/ababak/cgcpp.git
44
+
45
+ or
46
+
47
+ pip install cgcpp
48
+
49
+ ## Building Examples
50
+
51
+ mkdir out
52
+ python -m cgcpp examples/source_exception --out ./out
53
+ python -m cgcpp examples/source_maya --out ./out --maya
54
+ python -m cgcpp examples/source_houdini --out ./out --houdini
55
+
56
+ Ensure you have Maya and Houdini installed in their default locations as specified in `CMakeLists.txt`
57
+
58
+ ## Testing Built Examples
59
+ Should throw `AttributeError: Some error` exception:
60
+
61
+ python -c 'import cgcpp;cgcpp.call(lib="out/lib_exception", func="call")'
62
+
63
+ Inside Maya:
64
+
65
+ import cgcpp
66
+ print(cgcpp.call(lib="out/maya_module", func="ls"))
67
+
68
+ Inside Houdini:
69
+
70
+ import cgcpp
71
+ print(cgcpp.call(lib="out/houdini_module", func="ls"))
@@ -0,0 +1,11 @@
1
+ cgcpp/__init__.py,sha256=qf7rPszcBspZJtA33c7nQwnHju-ec-BzKX1mX-UXiF0,3881
2
+ cgcpp/__main__.py,sha256=SHNrpVIurEUdaCeHcorJn23jiP3O-6u41oY_qrcs6eg,2073
3
+ cgcpp/build.py,sha256=TizhFU3LBGCxUu0RnoTzSOMxAJIZpOzZGW1AButHXZg,2434
4
+ cgcpp/lib_loader_python310.pyd,sha256=RlKLAiIse_PtApdxfWuOPSIhHXF9mR0Om6n7CM8yyzI,134656
5
+ cgcpp/lib_loader_python311.pyd,sha256=hA8T1jXVZVqp85tpKl5-90U6c9a9Xqj61mD-iXJWsWs,134656
6
+ cgcpp/lib_loader_python312.pyd,sha256=LP6b_3yZjgvptXzGhB253kedmMuAySajjYEtgxjCam8,140288
7
+ cgcpp/lib_loader_python39.pyd,sha256=XJNC6gck1bGaD0MCcpMIGO4OCNorg3SnpSTgMnYpdlI,130048
8
+ cgcpp-1.8.2.dist-info/METADATA,sha256=nqgvIlu2tblbM6CL_DIbhVFqmQEH1HKrlLyUNvB1Cpc,2425
9
+ cgcpp-1.8.2.dist-info/WHEEL,sha256=Uot1xtv2NjZkWGfsbtixFxGSupJDmWFZZuntJdtO4yI,98
10
+ cgcpp-1.8.2.dist-info/top_level.txt,sha256=FiFBFxcRpL25SIiVvvzdLJgbYHR17k1haJMNvE2v3oM,6
11
+ cgcpp-1.8.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
5
+
@@ -0,0 +1 @@
1
+ cgcpp