The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
TYPEMAP
    char          *   T_PV
    unsigned char *   T_PV
    const char    *   T_PV
    AV            *   T_AVREF

    SSH2          *   O_SESSION
    SSH2_CHANNEL  *   O_CHANNEL
    SSH2_LISTENER *   O_LISTENER
    SSH2_SFTP     *   O_SFTP
    SSH2_FILE     *   O_FILE
    SSH2_DIR      *   O_DIR
    SSH2_PUBLICKEY*   O_PUBLICKEY

OUTPUT
T_PV
    sv_setpv((SV*)$arg, $var);

T_AVREF
    $arg = newRV((SV*)$var);

O_SESSION
    sv_setref_pv($arg, "Net::SSH2", (void *)$var);

O_CHANNEL
    {
    GV* gv = (GV*)newSVrv($arg, "Net::SSH2::Channel");
    IO* io = (IO*)newSV(0);
    const char* name = form("_GEN_%ld", (long)net_ch_gensym++);
    SvUPGRADE((SV*)gv, SVt_PVGV);
    SvUPGRADE((SV*)io, SVt_PVIO);
    SvIVX(gv) = PTR2IV($var);
    gv_init(gv, gv_stashpv("Net::SSH2::Channel", 0/*create*/),
     name, strlen(name), 0/*multi*/);
    GvIOp(gv) = io;
    sv_magic((SV*)io, newRV((SV*)gv), PERL_MAGIC_tiedscalar, Nullch, 0);
    }

O_LISTENER
    sv_setref_pv($arg, "Net::SSH2::Listener", (void *)$var);

O_SFTP
    sv_setref_pv($arg, "Net::SSH2::SFTP", (void *)$var);

O_FILE
    {
    GV* gv = (GV*)newSVrv($arg, "Net::SSH2::File");
    IO* io = (IO*)newSV(0);
    const char* name = form("_GEN_%ld", (long)net_fi_gensym++);
    SvUPGRADE((SV*)gv, SVt_PVGV);
    SvUPGRADE((SV*)io, SVt_PVIO);
    SvIVX(gv) = PTR2IV($var);
    gv_init(gv, gv_stashpv("Net::SSH2::File", 0/*create*/),
     name, strlen(name), 0/*multi*/);
    GvIOp(gv) = io;
    sv_magic((SV*)io, newRV((SV*)gv), PERL_MAGIC_tiedscalar, Nullch, 0);
    }

O_DIR
    sv_setref_pv($arg, "Net::SSH2::Dir", (void *)$var);

O_PUBLICKEY
    sv_setref_pv($arg, "Net::SSH2::PublicKey", (void *)$var);

INPUT
T_PV
    $var = ($type)SvPV_nolen($arg)

T_AVREF
    if(SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV)
        $var = (AV*)SvRV($arg);
    else
        croak(\"$var is not an array reference\");

O_SESSION
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
        $var = ($type)SvIV((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid session object\");

O_CHANNEL
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVGV))
        $var = ($type)SvIVX((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid channel object\");

O_LISTENER
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
        $var = ($type)SvIV((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid listener object\");

O_SFTP
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
        $var = ($type)SvIV((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid SFTP object\");

O_FILE
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVGV))
        $var = ($type)SvIVX((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid SFTP file object\");

O_DIR
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
        $var = ($type)SvIV((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid SFTP directory object\");

O_PUBLICKEY
    if(sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
        $var = ($type)SvIV((SV*)SvRV($arg));
    else
        croak(\"${Package}::$func_name() - invalid public key object\");