[Tutor] How to wrap ctype functions

Hugo Arts hugo.yoshi at gmail.com
Wed Mar 3 22:44:35 CET 2010


On Wed, Mar 3, 2010 at 6:43 PM, Jan Jansen <knacktus at googlemail.com> wrote:
> Hi there,
>
> I wonder what's the best way to wrap given function calls (in this case
> ctype function calls but more generally built-in functions and those kinds).
> I have a huge c library and almost all functions return an error code. The
> library also contains a function, that returns the corresponding error
> message to the error code. So, what I need to do for every call to one of
> the libraries functions looks like this:
>
> error_code = my_c_library.SOME_FUNCTION_
> CALL(argument)
> if error_code != 0:
>    error_message = my_c_library.GET_ERROR_TEXT(error_code)
>    print "error in function call SOME_FUNCTION_CALL"
>    print error_message
>    my_c_library.EXIT_AND_CLEAN_UP()
>
> Also, for some function calls I would need to do some preperations like:
>
> error_code = my_c_library.LOG_IN_AS_ADMINISTRATOR(admin_user,
> admin_password)
> error_code = my_c_library.SOME_FUNCTION_CALL(argument)
>
> I like the decorator idea, but I can't figure out if it's applicable here.
> To be able to call the function in a manner like this would be great, e.g.
>
> @change_user(admin_user, admin_password)
> @error_handling
> my_c_library.SOME_FUNCTION_CALL(argument)
>

Well, decorators only work on function definitions, not function
calls. What you could do is

a) write a function that takes your c function as an argument and does
the error handling for you

would probably look something like this:

def call_with_errorhandling(func, *args):
    error_code = func(*args)
    if error_code != 0:
        error_message = my_c_library.GET_ERROR_TEXT(error_code)
        print "error in function call SOME_FUNCTION_CALL"
        print error_message
        my_c_library.EXIT_AND_CLEAN_UP()

b) wrap all your c functions in a python function that does error handling.

the wrapper/decorator would look somewhat like this:

from functools import wraps

def with_error_handling(func):
    @wraps(func)
    def new_func(*args):
        error_code = func(*args)
        if error_code != 0:
            error_message = my_c_library.GET_ERROR_TEXT(error_code)
            print "error in function call SOME_FUNCTION_CALL"
            print error_message
            my_c_library.EXIT_AND_CLEAN_UP()
    return new_func

and you'd wrap functions with it like so:

# old syntax
wrapped_function = with_error_handling(library.some_C_function)

#decorator syntax
@with_error_handling
def wrapped_function(*args)
    return library.some_C_function(*args)

#just call your wrapped function now, the error handling will take place.
wrapped_function(argument)

You can write similar functions that do admin login in both ways. Both
approaches wrap C functions in python functions, so the overhead
should be about the same (the decorator way should consume somewhat
more memory, since it creates a new function object for everything you
wrap, but it's probably not very significant).

HTH,

Hugo


More information about the Tutor mailing list