Skip to content

6.1 Python에서 C99 SDK 연동

개요

Python 애플리케이션은 ctypes 를 통해 C99 SDK 동적 라이브러리를 호출하여 언어 간 통합을 구현할 수 있습니다.

6.1.1 환경 준비

의존성설명
Python3.6+
C99 SDKc_arm_api.dll (Windows) 또는 libc_arm_api.so (Linux)

6.1.2 최소 예제: 연결 및 연결 해제

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

import ctypes

# C99 SDK 동적 라이브러리를 로드합니다.
arm_api = ctypes.CDLL("c_arm_api.dll")

# 핸들을 생성합니다.
handle = arm_api.Arm_Create()

# 로봇에 연결합니다.
ret = arm_api.Arm_Connect(handle, b"10.27.1.2", b"10.27.1.102")
print(f"연결 결과: {ret}")

# 연결을 해제합니다.
arm_api.Arm_Disconnect(handle)

# 핸들을 파괴합니다.
arm_api.Arm_Destroy(handle)
print("완료")

6.1.3 객체 지향 래퍼(퍼사드 패턴)

Arm 클래스를 만들어 C99 함수를 Pythonic한 객체 지향 API로 래핑할 수 있습니다.

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

import ctypes

class Arm:
    """로봇 제어 퍼사드 클래스"""

    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):
        """함수 시그니처를 설정합니다."""
        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:
        """로봇에 연결합니다."""
        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"연결 실패: {ret}")

    def disconnect(self) -> None:
        """연결을 해제합니다."""
        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

# 사용 예제
with Arm() as arm:
    arm.connect("10.27.1.2", "10.27.1.102")
    print("연결 성공")

6.1.4 주의 사항

  1. 문자열 인코딩: 입력 문자열은 encode('utf-8')bytes 로 변환해야 합니다.
  2. DLL 경로: DLL이 검색 가능한 경로에 있는지 확인합니다.
  3. 스레드 안전: 같은 핸들을 여러 스레드에서 동시에 접근할 수 없습니다.
  4. BasScript Builder: C99는 ArmBasScriptHandle / ArmBasExtraParamHandle 을 제공하므로, Python 바인딩 계층에서 스크립트 구성 인터페이스를 객체로 래핑할 수 있습니다.
  5. Builder 편의 래퍼: Arm_BasScript_SetName / AppendLine(s)Arm_BasValue_* 는 Python 객체 메서드와 팩토리 함수로 매핑할 수 있습니다.