sub do_stuff { my ( $self, %args ) = @_; my $foo = $args{foo}; my $bar = $args{bar}; # .... } #### void do_stuff(self, ...) SV *self; PPCODE: { HV* args_hash = build_args_hash(args, to, be, named, later); IV foo = extract_iv(args_hash, "foo", 3); NV bar = extract_nv(args_hash, "bar", 3); /* ... */ } #### IV extract_iv(hash, key, key_len) { SV **const sv_ptr = hv_fetch(hash, key, key_len, 0); if (sv_ptr == NULL) { croak("Failed to retrieve hash entry '%s'", key); } return SvIV(*sv_ptr); } #### HV* build_args_hash() { dXSARGS; /* need to declare XS args so that we can use ST(n) later */ HV *args_hash = (HV*)sv_2mortal( (SV*)newHV() ); /* mortalized hash */ kino_i32_t stack_pos = 1; /* verify that our args come in pairs */ if (items % 2 != 1) { croak("Expecting hash-style named params, got odd number of args"); } /* build the hash */ while (stack_pos < items) { SV *val_sv; SV *key_sv = ST(stack_pos++); STRLEN key_len; char *key = SvPV(key_sv, key_len); val_sv = ST(stack_pos++); hv_store(args_hash, key, key_len, newSVsv(val_sv), 0); } return args_hash; } #### { PUSHMARK(SP); HV* args_hash = build_args_hash(); IV foo = extract_iv(args_hash, "foo", 3); NV bar = extract_nv(args_hash, "bar", 3); /* ... */ } #### { HV *args_hash; IV foo; NV bar; PUSHMARK(SP); args_hash = build_args_hash(); foo = extract_iv(args_hash, "foo", 3); bar = extract_nv(args_hash, "bar", 3); /* ... */ } #### HV *arg_hash = build_args_hash( &(ST(0)), items );