__init__.py 7.2 KB
from ctypes import *
import os

# some notes on ctypes:
# first, you have to make an object that talks directly to the compiled C object
# then, for each function in the C API, the user must define the input/return types
# not setting the argtypes means no args, not setting restypes is void
# there are the normal types, like c_int, c_bool, c_float, c_int_p (char*)
# for char** and *char[], we use POINTER(c_char_p)
# and c_void_p for void*

# these helper functions are just for code reuse -
# they generate common arguments for the  C API functions

def _string_args(n):
    '''
    Returns n char*
    '''
    s  = []
    for i in range(n):
        s.append(c_char_p)
    return s

def _var_string_args(n):
    '''
    Returns one int and one char** followed by n char*
    '''
    s = [c_int, POINTER(c_char_p)]
    s.extend(_string_args(n))
    return s

def _handle_string_func(func):
    '''
    A helper function to make the C functions 
    that populate string buffers more pythonic.
    The functions in the C API return an int 
    (the length of the returned string buffer) 
    and put the return value in a string buffer.
    This function replaces the call to the C obj with two calls - 
        a) one with empty string to get length
        b) one with a string of that length to get the actual value
    Then it returns the string itself. This way, the user of brpy 
    doesn't need to do this stupid magic for themselves. Hooray!
    '''
    def call_func(*args):
        howlong = func('', 0, *args)
        msg = 'x'*(howlong-1)
        func(msg, howlong, *args)
        return msg
    return call_func

def init_brpy(br_loc='/usr/local/lib'):
    """Initializes all function inputs and outputs for the br ctypes lib object"""

    lib_path = os.environ.get('LD_LIBRARY_PATH')
    paths = [br_loc]
    if lib_path:
        paths.extend(lib_path.split(':'))

    found = False
    for p in paths:
        dylib = '%s/%s.%s' % (p, 'libopenbr', 'dylib')
        so = '%s/%s.%s' % (p, 'libopenbr', 'so')
        if os.path.exists(dylib):
            br = cdll.LoadLibrary(dylib)
            found = True
            break
        elif os.path.exists(so):
            br = cdll.LoadLibrary(so)
            found = True
            break

    if not found:
        raise ValueError('Neither .so nor .dylib libopenbr found in %s' % br_loc)

    plot_args = _var_string_args(1) + [c_bool]
    br.br_about.restype = c_char_p
    br.br_cat.argtypes = _var_string_args(1)
    br.br_cluster.argtypes = [c_int, POINTER(c_char_p), c_float, c_char_p]
    br.br_combine_masks.argtypes = _var_string_args(2)
    br.br_compare.argtypes = _string_args(3)
    br.br_compare_n.argtypes = [c_int, POINTER(c_char_p)] + _string_args(2)
    br.br_pairwise_compare.argtypes = _string_args(3)
    br.br_convert.argtypes = _string_args(3)
    br.br_enroll.argtypes = _string_args(2)
    br.br_enroll_n.argtypes = _var_string_args(1)
    br.br_eval.argtypes = _string_args(3)
    br.br_eval.restype = c_float
    br.br_eval_classification.argtypes = _string_args(4)
    br.br_eval_clustering.argtypes = _string_args(3)
    br.br_eval_detection.argtypes = _string_args(3)
    br.br_eval_detection.restype = c_float
    br.br_eval_landmarking.argtypes = _string_args(3) + [c_int, c_int]
    br.br_eval_landmarking.restype = c_float
    br.br_eval_regression.argtypes = _string_args(4)
    br.br_fuse.argtypes = _var_string_args(3)
    br.br_initialize.argtypes = _var_string_args(1)
    br.br_is_classifier.argtypes = [c_char_p]
    br.br_is_classifier.restype = c_bool
    br.br_make_mask.argtypes = _string_args(3)
    br.br_make_pairwise_mask.argtypes = _string_args(3)
    br.br_most_recent_message.argtypes = [c_char_p, c_int]
    br.br_most_recent_message.restype = c_int
    func = br.br_most_recent_message.__call__
    br.br_most_recent_message = _handle_string_func(func)
    br.br_objects.argtypes = [c_char_p, c_int] + _string_args(2) + [c_bool]
    br.br_objects.restype = c_int
    func2 = br.br_objects.__call__
    br.br_objects = _handle_string_func(func2)
    br.br_plot.argtypes = plot_args
    br.br_plot.restype = c_bool
    br.br_plot_detection.argtypes = plot_args
    br.br_plot_detection.restype = c_bool
    br.br_plot_landmarking.argtypes = plot_args
    br.br_plot_landmarking.restype = c_bool
    br.br_plot_metadata.argtypes = plot_args
    br.br_plot_metadata.restype = c_bool
    br.br_progress.restype = c_float
    br.br_read_pipe.argtypes = [c_char_p, POINTER(c_int), POINTER(POINTER(c_char_p))]
    br.br_scratch_path.argtypes = [c_char_p, c_int]
    br.br_scratch_path.restype = c_int
    func3 = br.br_scratch_path.__call__
    br.br_scratch_path = _handle_string_func(func3)
    br.br_sdk_path.restype = c_char_p
    br.br_get_header.argtypes = [c_char_p, POINTER(c_char_p), POINTER(c_char_p)]
    br.br_set_header.argtypes = _string_args(3)
    br.br_set_property.argtypes = _string_args(2)
    br.br_time_remaining.restype = c_int
    br.br_train.argtypes = _string_args(2)
    br.br_train_n.argtypes = _var_string_args(1)
    br.br_version.restype = c_char_p
    br.br_slave_process.argtypes = [c_char_p]
    br.br_load_img.argtypes = [c_char_p, c_int]
    br.br_load_img.restype = c_void_p
    br.br_unload_img.argtypes = [c_void_p]
    br.br_unload_img.restype = POINTER(c_ubyte)
    br.br_template_list_from_buffer.argtypes = [c_char_p, c_int]
    br.br_template_list_from_buffer.restype = c_void_p
    br.br_free_template.argtypes = [c_void_p]
    br.br_free_template_list.argtypes = [c_void_p]
    br.br_free_output.argtypes = [c_void_p]
    br.br_img_rows.argtypes = [c_void_p]
    br.br_img_rows.restype = c_int
    br.br_img_cols.argtypes = [c_void_p]
    br.br_img_cols.restype = c_int
    br.br_img_channels.argtypes = [c_void_p]
    br.br_img_channels.restype = c_int
    br.br_img_is_empty.argtypes = [c_void_p]
    br.br_img_is_empty.restype = c_bool
    br.br_get_filename.argtypes = [c_char_p, c_int, c_void_p]
    br.br_get_filename.restype = c_int
    func4 = br.br_get_filename.__call__
    br.br_get_filename = _handle_string_func(func4)
    br.br_set_filename.argtypes = [c_void_p, c_char_p]
    br.br_get_metadata_string.argtypes = [c_char_p, c_int, c_void_p, c_char_p]
    br.br_get_metadata_string.restype = c_int
    func5 = br.br_get_metadata_string.__call__
    br.br_get_metadata_string = _handle_string_func(func5)
    br.br_enroll_template.argtypes = [c_void_p]
    br.br_enroll_template.restype = c_void_p
    br.br_enroll_template_list.argtypes = [c_void_p]
    br.br_enroll_template_list.restype = c_void_p
    br.br_compare_template_lists.argtypes = [c_void_p, c_void_p]
    br.br_compare_template_lists.restype = c_void_p
    br.br_get_matrix_output_at.argtypes = [c_void_p, c_int, c_int]
    br.br_get_matrix_output_at.restype = c_float
    br.br_get_template.argtypes = [c_void_p, c_int]
    br.br_get_template.restype = c_void_p
    br.br_num_templates.argtypes = [c_void_p]
    br.br_num_templates.restype = c_int
    br.br_make_gallery.argtypes = [c_char_p]
    br.br_make_gallery.restype = c_void_p
    br.br_load_from_gallery.argtypes = [c_void_p]
    br.br_load_from_gallery.restype = c_void_p
    br.br_add_template_to_gallery.argtypes = [c_void_p, c_void_p]
    br.br_add_template_list_to_gallery.argtypes = [c_void_p, c_void_p]
    br.br_close_gallery.argtypes = [c_void_p]

    return br