The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

XS::Framework::Manual::SVAPI::CallProxy - XS::Framework CallProxy C++ class reference

CallProxy

The CallProxy is helper class which Perl method invocation. The need of this class is due to invocation context, which can be list, scalar or void, and the lack of direct language equivalent in C/C++.

Another notable feature is that actual method invocation is postponed, until the relevant context is supplied (or void context will be supplied). So, for example the in the following code

    Sub sub = ...;
    CallProxy result = sub.call();
    int a = 5;

The variable a will always be assigned first before a Perl method invocation. However, in the following code:

    Sub sub = ...;
    sub.call();
    int a = 5;

a Perl method will be invoked first, and only then the variable a will be assigned. This happens, because CallProxy destructor is invoked, and it is able to detect, the condition, that it was not invoked, so it performs Perl subroutine invocation in the destructor.

Let's take another example:

    Sub sub1 = ...;
    Sub sub2 = ...;
    CallProxy r1 = sub1.call();
    CallProxy r2 = sub2.call();
    Sv sv2 = r2.scalar();
    Sv sv1 = r1.scalar();

Here the actual order of calls is: sub2, then sub1, because the invocation is performed at the moment of context-sensitive result access.

Due to that subtle compexities recording CallProxy is discouraged. We advice to use it only as transient object, i.e. convert to the final class immediately, e.g.

    Simple = sub1.call(...);

Construction

    CallProxy (CV* cv, SV* arg = NULL, SV*const* args = NULL, size_t items = 0)
    CallProxy (CV* cv, SV* arg, const Scalar* args, size_t items)

Creates new CallProxy, "currying" the Perl sub (CV*) and arguments. The Perl subrouite itself is not executed.

The CV* must be not NULL.

Result access and actual invocation

It is possible to invoke the CallProxy in the list context and do appropriate types unpacking in C++

    template <class T, size_t N, typename = one_of_t<T,Sv,Scalar,Ref,Simple>>
    operator std::array<T,N> ()

    template <class... Types>
    operator std::tuple<Types...> ()

for example

    using result_t = std::array<Sv, 2>;
    Sub sub = ...;
    result_t res = sub.call();

This is mostly useful if Perl interface is known apriory from C++, and the list result will be no longer used in Perl.

To perform a call in list / scalar context, the following methods should be used:

    Scalar scalar () const
    Array  list   () const

If it is known, that the result of a call is Simple, it is possible to get the string or number via:

    template <class T = panda::string> T as_string () const
    template <class T = int> T as_number () const

For example:

    Sub sub = ...;
    int count = sub.call(...).as_number();

An perl subroutine is executed in scalar context above. If the result is not conversible to Simple runtime exception will be thrown.

call()

    CallProxy call (const panda::string_view& name)
    CallProxy call (const panda::string_view& name, const Scalar& arg)
    CallProxy call (const panda::string_view& name, SV*const* args, size_t items)
    CallProxy call (const panda::string_view& name, std::initializer_list<Scalar> l)

if it is known a priory, that the result of the invocation is Object, then it is possible to have "chaned call" approach, i.e.

    Object obj = ...;
    obj.call("method1", ...).call("method2", ...).call("method3", ...)

The corresponding Perl construct for this is:

    $obj->method1->method2->method3;

SEE ALSO

XS::Framework

XS::Framework::Manual::SVAPI

XS::Framework::Manual::SVAPI::Sub

XS::Framework::Manual::SVAPI::Object

XS::Framework::Manual::SVAPI::Ref

XS::Framework::Manual::SVAPI::Stash