Skip to content

Python:ctypes

CDLL Example

import ctypes
libc = ctypes.CDLL(None)
c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout')  # stdout 획득 방법.
libc.puts(b'this comes from C')  # puts 호출 방법.

Refactoring

pylibdmtxdmtx_library.py 의 파일 예제:

"""Loads libdmtx.
"""
import platform
import sys

from ctypes import cdll
from ctypes.util import find_library
from pathlib import Path

__all__ = ['load']


def _windows_fname():
    """For convenience during development and to aid debugging, the DLL name is
    specific to the bit depth of interpreter.

    This logic has its own function to make testing easier
    """
    return 'libdmtx-64.dll' if sys.maxsize > 2**32 else 'libdmtx-32.dll'


def load():
    """Loads the libdmtx shared library.
    """
    if 'Windows' == platform.system():
        # Possible scenarios here
        #   1. Run from source, DLLs are in pylibdmtx directory
        #       cdll.LoadLibrary() imports DLLs in repo root directory
        #   2. Wheel install into CPython installation
        #       cdll.LoadLibrary() imports DLLs in package directory
        #   3. Wheel install into virtualenv
        #       cdll.LoadLibrary() imports DLLs in package directory
        #   4. Frozen
        #       cdll.LoadLibrary() imports DLLs alongside executable

        fname = _windows_fname()
        try:
            libdmtx = cdll.LoadLibrary(fname)
        except OSError:
            libdmtx = cdll.LoadLibrary(
                str(Path(__file__).parent.joinpath(fname))
            )
    else:
        # Assume a shared library on the path
        path = find_library('dmtx')
        if not path:
            raise ImportError('Unable to find dmtx shared library')
        libdmtx = cdll.LoadLibrary(path)

    return libdmtx

c_void_p

C의 NULL 포인터는 ctypes.c_void_p(0)로 만들 수 있다.

memmove Example

C 포인터 주소는 addressof 를 사용하는데, 인자는 ctypes 형의 인스턴스가 필요하다.

일반 Python bytes 객체의 ctypes 형 인스턴스는 create_string_buffer를 사용하면 된다.

from ctypes import addressof, create_string_buffer, memmove

pixels = ...
size = width * height * channels

assert isinstance(pixels, bytes)
assert isinstance(size, int)

buffer_ptr = GL.glMapBuffer(GL.GL_PIXEL_UNPACK_BUFFER, GL.GL_WRITE_ONLY)
if buffer_ptr:
    pixels_ptr = addressof(create_string_buffer(pixels, size))
    memmove(buffer_ptr, pixels_ptr, size)
    GL.glUnmapBuffer(GL.GL_PIXEL_UNPACK_BUFFER)

See also

Favorite site