functional.h revision 11986
111986Sandreas.sandberg@arm.com/* 211986Sandreas.sandberg@arm.com pybind11/functional.h: std::function<> support 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.com All rights reserved. Use of this source code is governed by a 711986Sandreas.sandberg@arm.com BSD-style license that can be found in the LICENSE file. 811986Sandreas.sandberg@arm.com*/ 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com#pragma once 1111986Sandreas.sandberg@arm.com 1211986Sandreas.sandberg@arm.com#include "pybind11.h" 1311986Sandreas.sandberg@arm.com#include <functional> 1411986Sandreas.sandberg@arm.com 1511986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(pybind11) 1611986Sandreas.sandberg@arm.comNAMESPACE_BEGIN(detail) 1711986Sandreas.sandberg@arm.com 1811986Sandreas.sandberg@arm.comtemplate <typename Return, typename... Args> struct type_caster<std::function<Return(Args...)>> { 1911986Sandreas.sandberg@arm.com typedef std::function<Return(Args...)> type; 2011986Sandreas.sandberg@arm.com typedef typename std::conditional<std::is_same<Return, void>::value, void_type, Return>::type retval_type; 2111986Sandreas.sandberg@arm.compublic: 2211986Sandreas.sandberg@arm.com bool load(handle src_, bool) { 2311986Sandreas.sandberg@arm.com if (src_.is_none()) 2411986Sandreas.sandberg@arm.com return true; 2511986Sandreas.sandberg@arm.com 2611986Sandreas.sandberg@arm.com src_ = detail::get_function(src_); 2711986Sandreas.sandberg@arm.com if (!src_ || !PyCallable_Check(src_.ptr())) 2811986Sandreas.sandberg@arm.com return false; 2911986Sandreas.sandberg@arm.com 3011986Sandreas.sandberg@arm.com /* 3111986Sandreas.sandberg@arm.com When passing a C++ function as an argument to another C++ 3211986Sandreas.sandberg@arm.com function via Python, every function call would normally involve 3311986Sandreas.sandberg@arm.com a full C++ -> Python -> C++ roundtrip, which can be prohibitive. 3411986Sandreas.sandberg@arm.com Here, we try to at least detect the case where the function is 3511986Sandreas.sandberg@arm.com stateless (i.e. function pointer or lambda function without 3611986Sandreas.sandberg@arm.com captured variables), in which case the roundtrip can be avoided. 3711986Sandreas.sandberg@arm.com */ 3811986Sandreas.sandberg@arm.com if (PyCFunction_Check(src_.ptr())) { 3911986Sandreas.sandberg@arm.com auto c = reinterpret_borrow<capsule>(PyCFunction_GetSelf(src_.ptr())); 4011986Sandreas.sandberg@arm.com auto rec = (function_record *) c; 4111986Sandreas.sandberg@arm.com using FunctionType = Return (*) (Args...); 4211986Sandreas.sandberg@arm.com 4311986Sandreas.sandberg@arm.com if (rec && rec->is_stateless && rec->data[1] == &typeid(FunctionType)) { 4411986Sandreas.sandberg@arm.com struct capture { FunctionType f; }; 4511986Sandreas.sandberg@arm.com value = ((capture *) &rec->data)->f; 4611986Sandreas.sandberg@arm.com return true; 4711986Sandreas.sandberg@arm.com } 4811986Sandreas.sandberg@arm.com } 4911986Sandreas.sandberg@arm.com 5011986Sandreas.sandberg@arm.com auto src = reinterpret_borrow<object>(src_); 5111986Sandreas.sandberg@arm.com value = [src](Args... args) -> Return { 5211986Sandreas.sandberg@arm.com gil_scoped_acquire acq; 5311986Sandreas.sandberg@arm.com object retval(src(std::move(args)...)); 5411986Sandreas.sandberg@arm.com /* Visual studio 2015 parser issue: need parentheses around this expression */ 5511986Sandreas.sandberg@arm.com return (retval.template cast<Return>()); 5611986Sandreas.sandberg@arm.com }; 5711986Sandreas.sandberg@arm.com return true; 5811986Sandreas.sandberg@arm.com } 5911986Sandreas.sandberg@arm.com 6011986Sandreas.sandberg@arm.com template <typename Func> 6111986Sandreas.sandberg@arm.com static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { 6211986Sandreas.sandberg@arm.com if (!f_) 6311986Sandreas.sandberg@arm.com return none().inc_ref(); 6411986Sandreas.sandberg@arm.com 6511986Sandreas.sandberg@arm.com auto result = f_.template target<Return (*)(Args...)>(); 6611986Sandreas.sandberg@arm.com if (result) 6711986Sandreas.sandberg@arm.com return cpp_function(*result, policy).release(); 6811986Sandreas.sandberg@arm.com else 6911986Sandreas.sandberg@arm.com return cpp_function(std::forward<Func>(f_), policy).release(); 7011986Sandreas.sandberg@arm.com } 7111986Sandreas.sandberg@arm.com 7211986Sandreas.sandberg@arm.com PYBIND11_TYPE_CASTER(type, _("Callable[[") + 7311986Sandreas.sandberg@arm.com argument_loader<Args...>::arg_names() + _("], ") + 7411986Sandreas.sandberg@arm.com type_caster<retval_type>::name() + 7511986Sandreas.sandberg@arm.com _("]")); 7611986Sandreas.sandberg@arm.com}; 7711986Sandreas.sandberg@arm.com 7811986Sandreas.sandberg@arm.comNAMESPACE_END(detail) 7911986Sandreas.sandberg@arm.comNAMESPACE_END(pybind11) 80