pythonmacos

Call function from macos framework (e.g. IntelPowerGadget)


I'll say right away - this is my second day working with Python. So the question is probably simple. But for 2 days now I have not been able to find an answer to it. I want to use functions from the MacOS framework (IntelPowerGadget). At the moment I have written the following

if sys.platform == 'darwin':
    bundle = objc.loadBundle(
            "IntelPowerGadget",
            bundle_path="/Library/Frameworks/IntelPowerGadget.framework",
            module_globals=globals(),
    )
    functions = [('PG_Initialize', objc._C_VOID),]
                 #('PG_ReadSample',...),
                 #('PGSample_GetPackageTemperature',...)]
    objc.loadBundleFunctions(bundle, globals(), functions)
    PG_Initialize()

I can't figure out how to correctly describe and call PG_ReadSample (bool PG_ReadSample(int iPackage, PGSampleID* sampleID)) and PGSample_GetPackageTemperature(bool PGSample_GetPackageTemperature(PGSampleID sampleID, double* temp)). I can't find enough documentation either (I'd appreciate links - if I'm looking in the wrong place).

upd with @ali-saberi answer:

import objc
import ctypes
import sys

if sys.platform == 'darwin':
  # Load the Intel Power Gadget framework
  bundle = objc.loadBundle(
    "IntelPowerGadget",
    bundle_path="/Library/Frameworks/IntelPowerGadget.framework",
    module_globals=globals(),
  )

# Define PGSampleID as ctypes type (assuming it's an integer or a pointer type)
PGSampleID = ctypes.c_void_p  # Assuming PGSampleID is a pointer. Adjust if it's another type.

# Define the functions
functions = [
    ('PG_Initialize', objc._C_BOOL),
    ('PG_ReadSample',  objc._C_BOOL + objc._C_INT + objc._C_PTR + objc._C_ULNG_LNG),
    ('PGSample_GetPackageTemperature', objc._C_BOOL + objc._C_ULNG_LNG + objc._C_PTR + objc._C_DBL),
]

# Load the functions
objc.loadBundleFunctions(bundle, globals(), functions)

# Initialize the library
if not PG_Initialize():
    print("Failed to initialize Intel Power Gadget")
    sys.exit(1)

# Use PG_ReadSample
sample_id = PGSampleID()  # Placeholder for PGSampleID pointer
iPackage = 0  # Assume we're reading from package 0

if PG_ReadSample(iPackage, ctypes.byref(sample_id)):
    print("Sample read successfully")

    # Use PGSample_GetPackageTemperature
    temperature = ctypes.c_double()
    if PGSample_GetPackageTemperature(sample_id, ctypes.byref(temperature)):
        print(f"Package Temperature: {temperature.value}°C")
    else:
        print("Failed to get package temperature")
else:
    print("Failed to read sample")

there is error on "if PG_ReadSample(iPackage, ctypes.byref(sample_id)):":
"ValueError: depythonifying 'pointer', got 'CArgObject'"


Solution

  • working code

    if sys.platform == 'darwin':
            bundle = objc.loadBundle(
                "IntelPowerGadget",
                # bundle_path="/System/Library/Frameworks/IntelPowerGadget.framework",
                bundle_path="/Library/Frameworks/IntelPowerGadget.framework",
                module_globals=globals(),
    
            )
    
        functions = [
            #the first parameter is always bool - method was successfully/unsuccessfully executed
            #the last parameter is the return(_C_OUT) value as a pointer(_C_PTR). When calling, we specify it as None, but as second return value 
            #bool PG_Initialize(void)
            ('PG_Initialize', objc._C_BOOL),
            #bool PG_ReadSample(int iPackage, PGSampleID* sampleID)
            ('PG_ReadSample', objc._C_BOOL + objc._C_INT + objc._C_OUT + objc._C_PTR + objc._C_ULNG_LNG),
            #bool PGSample_GetPackageTemperature(PGSampleID sampleID, double* temp)
            ('PGSample_GetPackageTemperature', objc._C_BOOL + objc._C_ULNG_LNG + objc._C_OUT + objc._C_PTR + objc._C_DBL),
        ]
    
        objc.loadBundleFunctions(bundle, globals(), functions)
        if not PG_Initialize():
            print("Failed to initialize Intel Power Gadget")
            sys.exit(1)
        iPackage = 0
        result, sample_id = PG_ReadSample(iPackage, None)
        if result:
            print("Sample read successfully")
    
            # Use PGSample_GetPackageTemperature
            temp_result, temperature = PGSample_GetPackageTemperature(sample_id, None)
            if temp_result:
                print(f"Package Temperature: {temperature}°C")
            else:
                print("Failed to get package temperature")
        else:
            print("Failed to read sample")