File size: 5,085 Bytes
14a799a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import ctypes
import os
import platform

def check_error(code: int) -> None:
    if code != 0:
        raise Exception(f"API้”™่ฏฏ: {code}")

base_dir = os.path.dirname(__file__)
arch = platform.machine()

if arch == 'x86_64':
    arch_dir = 'x86_64'
elif arch in ('aarch64', 'arm64'):
    arch_dir = 'aarch64'
else:
    raise RuntimeError(f"Unsupported architecture: {arch}")

lib_paths = [
    os.path.join(base_dir, arch_dir, 'libclip.so'),
    os.path.join(base_dir, 'libclip.so')
]

last_error = None
diagnostic_shown = set()

for lib_path in lib_paths:
    try:
        print(f"Trying to load: {lib_path}")
        _lib = ctypes.CDLL(lib_path)
        print(f"โœ… Successfully loaded: {lib_path}")
        break
    except OSError as e:
        last_error = e
        err_str = str(e)
        print(f"\nโŒ Failed to load: {lib_path}")
        print(f"   {err_str}")

        # Only show GLIBCXX tip once
        if "GLIBCXX" in err_str and "not found" in err_str:
            if "missing_glibcxx" not in diagnostic_shown:
                diagnostic_shown.add("missing_glibcxx")
                print("๐Ÿ” Detected missing GLIBCXX version in libstdc++.so.6")
                print("๐Ÿ’ก This usually happens when your environment (like Conda) uses an older libstdc++")
                print(f"๐Ÿ‘‰ Try running with system libstdc++ preloaded:")
                print(f"   export LD_PRELOAD=/usr/lib/{arch_dir}-linux-gnu/libstdc++.so.6\n")
        elif "No such file" in err_str:
            if "file_not_found" not in diagnostic_shown:
                diagnostic_shown.add("file_not_found")
                print("๐Ÿ” File not found. Please verify that libclip.so exists and the path is correct.\n")
        elif "wrong ELF class" in err_str:
            if "elf_mismatch" not in diagnostic_shown:
                diagnostic_shown.add("elf_mismatch")
                print("๐Ÿ” ELF class mismatch โ€” likely due to architecture conflict (e.g., loading x86_64 .so on aarch64).")
                print(f"๐Ÿ‘‰ Run `file {lib_path}` to verify the binary architecture.\n")
        else:
            if "generic_error" not in diagnostic_shown:
                diagnostic_shown.add("generic_error")
                print("๐Ÿ“Ž Tip: Use `ldd` to inspect missing dependencies:")
                print(f"   ldd {lib_path}\n")
else:
    raise RuntimeError(f"\nโ— Failed to load libclip.so.\nLast error:\n{last_error}")


# ๅฎšไน‰ๆžšไธพ็ฑปๅž‹
class AxDeviceType(ctypes.c_int):
    unknown_device = 0
    host_device = 1
    axcl_device = 2

# ๅฎšไน‰็ป“ๆž„ไฝ“
class AxMemInfo(ctypes.Structure):
    _fields_ = [
        ('remain', ctypes.c_int),
        ('total', ctypes.c_int)
    ]

class AxHostInfo(ctypes.Structure):
    _fields_ = [
        ('available', ctypes.c_char),
        ('version', ctypes.c_char * 32),
        ('mem_info', AxMemInfo)
    ]

class AxDeviceInfo(ctypes.Structure):
    _fields_ = [
        ('temp', ctypes.c_int),
        ('cpu_usage', ctypes.c_int),
        ('npu_usage', ctypes.c_int),
        ('mem_info', AxMemInfo)
    ]

class AxDevices(ctypes.Structure):
    _fields_ = [
        ('host', AxHostInfo),
        ('host_version', ctypes.c_char * 32),
        ('dev_version', ctypes.c_char * 32),
        ('count', ctypes.c_ubyte),
        ('devices_info', AxDeviceInfo * 16)
    ]


_lib.ax_dev_enum_devices.argtypes = [ctypes.POINTER(AxDevices)]
_lib.ax_dev_enum_devices.restype = ctypes.c_int

_lib.ax_dev_sys_init.argtypes = [AxDeviceType, ctypes.c_char]
_lib.ax_dev_sys_init.restype = ctypes.c_int

_lib.ax_dev_sys_deinit.argtypes = [AxDeviceType, ctypes.c_char]
_lib.ax_dev_sys_deinit.restype = ctypes.c_int

def enum_devices() -> dict:
    devices = AxDevices()
    check_error(_lib.ax_dev_enum_devices(ctypes.byref(devices)))
    
    return {
        'host': {
            'available': bool(devices.host.available[0]),
            'version': devices.host.version.decode('utf-8'),
            'mem_info': {
                'remain': devices.host.mem_info.remain,
                'total': devices.host.mem_info.total
            }
        },
        'devices': {
            'host_version': devices.host_version.decode('utf-8'),
            'dev_version': devices.dev_version.decode('utf-8'),
            'count': devices.count,
            'devices_info': [{
                'temp': dev.temp,
                'cpu_usage': dev.cpu_usage,
                'npu_usage': dev.npu_usage,
                'mem_info': {
                    'remain': dev.mem_info.remain,
                    'total': dev.mem_info.total
                }
            } for dev in devices.devices_info[:devices.count]]
        }
    }


def sys_init(dev_type: AxDeviceType = AxDeviceType.axcl_device, devid: int = 0) -> None:
    check_error(_lib.ax_dev_sys_init(dev_type, devid))


def sys_deinit(dev_type: AxDeviceType = AxDeviceType.axcl_device, devid: int = 0) -> None:
    check_error(_lib.ax_dev_sys_deinit(dev_type, devid))