Quickstart

from typing import Callable
from ctyped.toolbox import Library
from ctyped.types import CInt

# Define a library.
lib = Library('mylib.so')

# Structures are defined with the help of `structure` decorator
@lib.structure
class Box:

    one: int
    two: str
    innerbox: 'Box'  # That'll be a pointer.

# Type less with function names prefixes.
with lib.scope(prefix='mylib_'):

    # Describe function available in the library.
    @lib.function(name='otherfunc')
    def some_func(title: str, year: int) -> str:
        ...

    @lib.f  # `f` is a shortcut for function.
    def struct_func(src: Box) -> Box:
        ...

    with lib.s(prefix='mylib_grouped_', int_bits=64, int_sign=False):  # `s` is a shortcut for scope.

        class Thing(CInt):

            @lib.method(int_sign=True)  # Override `int_sign` from scope.
            def one(self, some: int) -> int:
                # Implicitly pass Thing instance alongside
                # with explicitly passed `some` arg.
                ...

            @lib.m  # `m` is a shortcut for method.
            def two(self, some:int, cfunc: Callable) -> int:
                # `cfunc` is a wrapper, calling an actual ctypes function.
                result = cfunc()
                # If no arguments, the wrapper will try to detect them automatically.
                return result + 1

    @lib.function
    def get_thing() -> Thing:
        ...

# Or you may use classes as namespaces.
@lib.cls(prefix='common_', str_type=CCharsW)
class Wide:

    @staticmethod
    @lib.function
    def get_utf(some: str) -> str:
        ...

# Bind ctype types to functions available in the library.
lib.bind_types()

# Call function from the library. Call ``mylib_otherfunc``
result_string = some_func('Hello!', 2019)
result_wide = Wide.get_utf('some')  # Call ``common_get_utf``

# Now to structures. Call ``mylib_struct_func``
mybox = struct_func(Box(one=35, two='dummy', innerbox=Box(one=100)))
# Let's pretend our function returns a box inside a box (similar to what's in the params).
mybox.one  # Access box field value.
mybox.innerbox.one  # Access values from nested objects.

thing = get_thing()

thing.one(12)  # Call ``mylib_mylib_grouped_one``.
thing.two(13)  # Call ``mylib_mylib_grouped_two``

Sniffing

To save some time on function definition you can use ctyped automatic code generator.

It won’t give you fully functional code, but is able to lower typing chore.

from ctyped.sniffer import NmSymbolSniffer

# We sniff library first.
sniffer = NmSymbolSniffer('/here/is/my/libsome.so')
sniffed = sniffer.sniff()

# Now let's generate ctyped code.
dumped = sniffed.to_ctyped()

# At last we save autogenerated code into a file.
with open('library.py', 'w') as f:
    f.write(dumped)

There’s also a shortcut to sniff an already defined library:

...
sniffed = lib.sniff()
dumped = result.to_ctyped()