# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
from os.path import join, exists, dirname, normpath
import sys
import os
import ctypes as C
# ============================
# general ctypes interface
# ============================
__DEBUG_CLIB__ = '--debug' in sys.argv or '--debug-clib' in sys.argv
[docs]def get_plat_specifier():
"""
Standard platform specifier used by distutils
"""
import distutils
try:
plat_name = distutils.util.get_platform()
except AttributeError:
plat_name = distutils.sys.platform
plat_specifier = '.%s-%s' % (plat_name, sys.version[0:3])
if hasattr(sys, 'gettotalrefcount'):
plat_specifier += '-pydebug'
return plat_specifier
[docs]def get_lib_fname_list(libname):
"""
Args:
libname (str): library name (e.g. 'hesaff', not 'libhesaff')
Returns:
list: libnames - list of plausible library file names
CommandLine:
python -m pyhesaff.ctypes_interface get_lib_fname_list
Example:
>>> from pyhesaff.ctypes_interface import * # NOQA
>>> libname = 'hesaff'
>>> libnames = get_lib_fname_list(libname)
>>> import ubelt as ub
>>> print('libnames = {}'.format(ub.repr2(libnames)))
"""
if sys.platform.startswith('linux'):
# TODO: correct ABI tags
spec_list = [get_plat_specifier(), '-manylinux1_x86_64', '']
else:
spec_list = [get_plat_specifier(), '']
prefix_list = ['lib' + libname]
if sys.platform.startswith('win32'):
prefix_list.append(libname)
ext = '.dll'
elif sys.platform.startswith('darwin'):
ext = '.dylib'
elif sys.platform.startswith('linux'):
ext = '.so'
else:
raise Exception('Unknown operating system: %s' % sys.platform)
# Construct priority ordering of libnames
libnames = [
''.join((prefix, spec, ext)) for spec in spec_list for prefix in prefix_list
]
return libnames
[docs]def get_lib_dpath_list(root_dir):
"""
input <root_dir>: deepest directory to look for a library (dll, so, dylib)
returns <libnames>: list of plausible directories to look.
"""
'returns possible lib locations'
get_lib_dpath_list = [
root_dir,
join(root_dir, 'lib'),
join(root_dir, 'build'),
join(root_dir, 'build', 'lib'),
]
return get_lib_dpath_list
[docs]def find_lib_fpath(libname, root_dir, recurse_down=True, verbose=False):
""" Search for the library """
lib_fname_list = get_lib_fname_list(libname)
tried_fpaths = []
class FoundLib(Exception):
pass
FINAL_LIB_FPATH = None
try:
for lib_fname in lib_fname_list:
if verbose:
print('--')
curr_dpath = root_dir
while curr_dpath is not None:
for lib_dpath in get_lib_dpath_list(curr_dpath):
lib_fpath = normpath(join(lib_dpath, lib_fname))
tried_fpaths.append(lib_fpath)
flag = exists(lib_fpath)
if verbose:
print('[c] Check: {}, exists={}'.format(lib_fpath, int(flag)))
if flag:
if verbose:
print('using: {}'.format(lib_fpath))
FINAL_LIB_FPATH = lib_fpath
raise FoundLib
_new_dpath = dirname(curr_dpath)
if _new_dpath == curr_dpath:
curr_dpath = None
break
else:
curr_dpath = _new_dpath
if not recurse_down:
break
except FoundLib:
pass
return FINAL_LIB_FPATH
msg = (
'\n[C!] find_lib_fpath(libname=%r root_dir=%r, recurse_down=%r, verbose=%r)'
% (libname, root_dir, recurse_down, verbose)
+ '\n[c!] Cannot FIND dynamic library'
)
print(msg)
print('\n[c!] Checked: '.join(tried_fpaths))
raise ImportError(msg)
[docs]def load_clib(libname, root_dir):
"""
Searches for a library matching libname and loads it
Args:
libname: library name (e.g. 'hesaff', not 'libhesaff')
root_dir: the deepest directory searched for the
library file (dll, dylib, or so).
Returns:
clib: a ctypes object used to interface with the library
"""
lib_fpath = find_lib_fpath(libname, root_dir)
try:
clib = C.cdll[lib_fpath]
def def_cfunc(return_type, func_name, arg_type_list):
'Function to define the types that python needs to talk to c'
cfunc = getattr(clib, func_name)
cfunc.restype = return_type
cfunc.argtypes = arg_type_list
clib.__LIB_FPATH__ = lib_fpath
return clib, def_cfunc, lib_fpath
except OSError as ex:
print('[C!] Caught OSError:\n%s' % ex)
errsuffix = 'Is there a missing dependency?'
except Exception as ex:
print('[C!] Caught Exception:\n%s' % ex)
errsuffix = 'Was the library correctly compiled?'
print('[C!] cwd=%r' % os.getcwd())
print('[C!] load_clib(libname=%r root_dir=%r)' % (libname, root_dir))
print('[C!] lib_fpath = %r' % lib_fpath)
errmsg = '[C] Cannot LOAD %r dynamic library. ' % (libname,) + errsuffix
print(errmsg)
raise ImportError(errmsg)
if __name__ == '__main__':
r"""
CommandLine:
python -m pyhesaff.ctypes_interface
python -m pyhesaff.ctypes_interface --allexamples
"""
import xdoctest
xdoctest.doctest_module(__file__)