Skip to content

6.1 Python Accessing C99 SDK

Overview

Python applications can call C99 SDK dynamic library via ctypes for cross-language integration.

6.1.1 Prerequisites

DependencyDescription
Python3.6+
C99 SDKc_arm_api.dll (Windows) or libc_arm_api.so (Linux)

6.1.2 Minimal Example: Connect and Disconnect

python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import ctypes

# Load C99 SDK dynamic library
arm_api = ctypes.CDLL("c_arm_api.dll")

# Create handle
handle = arm_api.Arm_Create()

# Connect to robot
ret = arm_api.Arm_Connect(handle, b"10.27.1.2", b"10.27.1.102")
print(f"Connect result: {ret}")

# Disconnect
arm_api.Arm_Disconnect(handle)

# Destroy handle
arm_api.Arm_Destroy(handle)
print("Done")

6.1.3 Object-Oriented Wrapper (Facade Pattern)

You can create an Arm class that wraps C99 functions into a Pythonic object-oriented API:

python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import ctypes

class Arm:
    """Robot control facade class"""

    def __init__(self, dll_path: str = "c_arm_api.dll"):
        self._api = ctypes.CDLL(dll_path)
        self._setup_signatures()
        self._handle = None

    def _setup_signatures(self):
        """Set up function signatures"""
        self._api.Arm_Create.argtypes = []
        self._api.Arm_Create.restype = ctypes.c_void_p

        self._api.Arm_Destroy.argtypes = [ctypes.c_void_p]
        self._api.Arm_Destroy.restype = None

        self._api.Arm_Connect.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p]
        self._api.Arm_Connect.restype = ctypes.c_int

        self._api.Arm_Disconnect.argtypes = [ctypes.c_void_p]
        self._api.Arm_Disconnect.restype = None

    def connect(self, controller_ip: str, teach_panel_ip: str = None) -> None:
        """Connect to robot"""
        if self._handle is None:
            self._handle = self._api.Arm_Create()
        ret = self._api.Arm_Connect(
            self._handle,
            controller_ip.encode('utf-8'),
            teach_panel_ip.encode('utf-8') if teach_panel_ip else None
        )
        if ret != 0:
            raise RuntimeError(f"Connect failed: {ret}")

    def disconnect(self) -> None:
        """Disconnect"""
        if self._handle:
            self._api.Arm_Disconnect(self._handle)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.disconnect()
        if self._handle:
            self._api.Arm_Destroy(self._handle)
        return False

# Usage example
with Arm() as arm:
    arm.connect("10.27.1.2", "10.27.1.102")
    print("Connected successfully")

6.1.4 Notes

  1. String Encoding: Input strings need encode('utf-8') to convert to bytes
  2. DLL Path: Ensure DLL is in searchable path
  3. Thread Safety: Same handle cannot be accessed concurrently across threads
  4. BasScript Builder: C99 now also provides ArmBasScriptHandle / ArmBasExtraParamHandle , so Python bindings can wrap script construction APIs instead of manually building const char** BAS line arrays
  5. Builder Convenience Wrappers: Arm_BasScript_SetName / AppendLine(s) and Arm_BasValue_* are good candidates for Python-side object methods and factory helpers, avoiding manual tag/intValue/doubleValue/stringValue