First, keep in mind I've never used XS. I can't guarantee the following works or even its soundness.
If you check the system typemap (lib/ExtUtils/typemap), you'll see the definition of T_PTROBJ. (What is T_OBJECT?) We can create a new rule based on T_PTROBJ to suit our needs.
# typedef struct bar* Bar; # typedef struct type_foo* Foo; TYPEMAP ####### Bar T_NULLABLE_PTROBJ Foo T_NULLABLE_PTROBJ INPUT ##### T_NULLABLE_PTROBJ if ( !SvOK( $arg ) ) { /* if not defined */ $var = NULL; } else if ( sv_derived_from( $arg, \"${ntype}\" ) ) { IV tmp = SvIV( (SV*)SvRV( $arg ) ); $var = INT2PTR( $type, tmp ); } else { Perl_croak( aTHX_ \"$var is not of type ${ntype}\" ) } OUTPUT ###### T_NULLABLE_PTROBJ if ( $var ) /* if defined */ sv_setref_pv( $arg, \"${ntype}\", (void*)$var ); else $arg = &PL_sv_undef;
The usage would be
my $foo = undef; my $bar = Foo::create_bar( $foo );
Update: I don't think addressing the problem in the typemap is the best method. This makes pointers of that type always nullable, whereas that should be decided on a per-function (and even per-argument) basis. That means we should addresses the issue in the XS stub.
# typedef struct bar* Bar; # typedef struct type_foo* Foo; # In typemap: # Bar T_PTROBJ # Foo T_PTROBJ struct bar* create_bar(foo_sv = 0) SV* foo_sv CODE: struct type_foo* foo = NULL; if ( !foo_sv ) { /* Use default of NULL. */ } else if ( !SvOK( foo_sv ) ) { /* Use default of NULL. */ } else if ( sv_derived_from( foo_sv, 'type_foo' ) ) { IV tmp = SvIV( (SV*)SvRV( foo_sv ) ); foo = INT2PTR( struct type_foo*, tmp ); } else { Perl_croak( aTHX_ "\$foo is not of type foo_type" ) } RETVAL = my_c_create_bar(foo); OUTPUT: RETVAL
Bonus: The = 0 and the if ( !foo_sv ) allows the parameter to be omitted. Feel free to remove this.
Update: Now uses tabs in typemap, as required.
Update: struct bar* and struct type_foo* are no good for type T_PTROBJ — search for T_PTROBJ_SPECIAL in perlxs — so I added typedefs.
In reply to Re: Passing NULL pointer through XS without "Use of uninitialized value in subroutine entry"
by ikegami
in thread Passing NULL pointer through XS without "Use of uninitialized value in subroutine entry"
by kscaldef
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |