in reply to Re: (tye)Re: XS question: typemap for a pointer to a pointer?
in thread XS question: typemap for a pointer to a pointer?

Can you post the generated C code that relates to the processing of the problem argument (near the top and bottom of each generated subroutine)? You want the pointer to be stashed as an opaque value (usually an unsigned long integer, UV). If you have the typemap class wrong then the C code might be trying to copy the data in the allocated buffer rather than just stashing the pointer's value.

I don't recall which typemap class is meant to do this and looking at the generated C code prevents me from having to assembly the pieces myself and possible get confused in the process (I'm often easily confused).

        - tye (but my friends call me "Tye")
  • Comment on (tye)Re2: XS question: typemap for a pointer to a pointer?

Replies are listed 'Best First'.
Re: (tye)Re2: XS question: typemap for a pointer to a pointer?
by Big Willy (Scribe) on Apr 11, 2001 at 09:51 UTC
    This what you're asking for?
    /* * This file was generated automatically by xsubpp version 1.9507 from + the * contents of LibnetRaw.xs. Do not edit this file, edit LibnetRaw.xs +instead. * * ANY CHANGES MADE HERE WILL BE LOST! * */ #line 1 "LibnetRaw.xs" #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "libnet.h" #line 17 "LibnetRaw.c" XS(XS_Net__LibnetRaw_libnet_open_raw_sock) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_open_raw_sock( +protocol)"); { int protocol = (int)SvIV(ST(0)); int RETVAL; dXSTARG; RETVAL = libnet_open_raw_sock(protocol); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_close_raw_sock) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_close_raw_sock +(fd)"); { int fd = (int)SvIV(ST(0)); int RETVAL; dXSTARG; RETVAL = libnet_close_raw_sock(fd); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_write_ip) { dXSARGS; if (items != 3) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_write_ip(sock, + packet, len)"); { int sock = (int)SvIV(ST(0)); u_char * packet = (u_char *)SvPV(ST(1),PL_na); int len = (int)SvIV(ST(2)); int RETVAL; dXSTARG; RETVAL = libnet_write_ip(sock, packet, len); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_do_checksum) { dXSARGS; if (items != 3) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_do_checksum(bu +f, protocol, len)"); { u_char buf = (u_char)SvUV(ST(0)); int protocol = (int)SvIV(ST(1)); int len = (int)SvIV(ST(2)); int RETVAL; dXSTARG; RETVAL = libnet_do_checksum(&buf, protocol, len); sv_setuv(ST(0), (UV)buf); SvSETMAGIC(ST(0)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_init_packet) { dXSARGS; if (items != 2) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_init_packet(p_ +size, buf)"); { size_t p_size = (size_t)SvIV(ST(0)); u_char * buf = (u_char *)SvPV(ST(1),PL_na); int RETVAL; dXSTARG; RETVAL = libnet_init_packet(p_size, &buf); sv_setpv((SV*)ST(1), buf); SvSETMAGIC(ST(1)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_destroy_packet) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_destroy_packet +(buf)"); { u_char * buf = (u_char *)SvPV(ST(0),PL_na); int RETVAL; dXSTARG; RETVAL = libnet_destroy_packet(&buf); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_name_resolve) { dXSARGS; if (items != 2) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_name_resolve(h +ostname, use_name)"); { u_char * hostname = (u_char *)SvPV(ST(0),PL_na); u_short use_name = (u_short)SvUV(ST(1)); u_long RETVAL; dXSTARG; RETVAL = libnet_name_resolve(hostname, use_name); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_build_ip) { dXSARGS; if (items != 11) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_build_ip(len, +tos, id, frag, ttl, prot, saddr, daddr, payload, payload_s, buf)"); { u_short len = (u_short)SvUV(ST(0)); u_char tos = (u_char)SvUV(ST(1)); u_short id = (u_short)SvUV(ST(2)); u_short frag = (u_short)SvUV(ST(3)); u_char ttl = (u_char)SvUV(ST(4)); u_char prot = (u_char)SvUV(ST(5)); u_long saddr = (u_long)SvUV(ST(6)); u_long daddr = (u_long)SvUV(ST(7)); const u_char * payload = (const u_char *)SvPV(ST(8),PL_na); int payload_s = (int)SvIV(ST(9)); u_char buf = (u_char)SvUV(ST(10)); int RETVAL; dXSTARG; RETVAL = libnet_build_ip(len, tos, id, frag, ttl, prot, saddr, + daddr, payload, payload_s, &buf); sv_setuv(ST(10), (UV)buf); SvSETMAGIC(ST(10)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_build_tcp) { dXSARGS; if (items != 10) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_build_tcp(spor +t, dport, seq, ack, control, win, urg, payload, payload_s, buf)"); { u_short sport = (u_short)SvUV(ST(0)); u_short dport = (u_short)SvUV(ST(1)); u_long seq = (u_long)SvUV(ST(2)); u_long ack = (u_long)SvUV(ST(3)); u_char control = (u_char)SvUV(ST(4)); u_short win = (u_short)SvUV(ST(5)); u_short urg = (u_short)SvUV(ST(6)); const u_char * payload = (const u_char *)SvPV(ST(7),PL_na); int payload_s = (int)SvIV(ST(8)); u_char buf = (u_char)SvUV(ST(9)); int RETVAL; dXSTARG; RETVAL = libnet_build_tcp(sport, dport, seq, ack, control, win +, urg, payload, payload_s, &buf); sv_setuv(ST(9), (UV)buf); SvSETMAGIC(ST(9)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } #ifdef __cplusplus extern "C" #endif XS(boot_Net__LibnetRaw) { dXSARGS; char* file = __FILE__; XS_VERSION_BOOTCHECK ; newXS("Net::LibnetRaw::libnet_open_raw_sock", XS_Net__LibnetRa +w_libnet_open_raw_sock, file); newXS("Net::LibnetRaw::libnet_close_raw_sock", XS_Net__LibnetR +aw_libnet_close_raw_sock, file); newXS("Net::LibnetRaw::libnet_write_ip", XS_Net__LibnetRaw_lib +net_write_ip, file); newXS("Net::LibnetRaw::libnet_do_checksum", XS_Net__LibnetRaw_ +libnet_do_checksum, file); newXS("Net::LibnetRaw::libnet_init_packet", XS_Net__LibnetRaw_ +libnet_init_packet, file); newXS("Net::LibnetRaw::libnet_destroy_packet", XS_Net__LibnetR +aw_libnet_destroy_packet, file); newXS("Net::LibnetRaw::libnet_name_resolve", XS_Net__LibnetRaw +_libnet_name_resolve, file); newXS("Net::LibnetRaw::libnet_build_ip", XS_Net__LibnetRaw_lib +net_build_ip, file); newXS("Net::LibnetRaw::libnet_build_tcp", XS_Net__LibnetRaw_li +bnet_build_tcp, file); XSRETURN_YES; }
    Just for concenience, the typemap:
    u_char * T_PV u_char T_UV u_short T_UV u_long T_UV const u_char * T_PV
    Perhaps I am thinking of a pointer to a pointer in the wrong fashion or I am confusing the ways in which perl reference work that I am not clear on. I truly appreciate your help!

      Yeah, that's it! Now for the relavent bits:

      XS(XS_Net__LibnetRaw_libnet_do_checksum) [...] u_char buf = (u_char)SvUV(ST(0)); [...] RETVAL = libnet_do_checksum(&buf, protocol, len); sv_setuv(ST(0), (UV)buf); SvSETMAGIC(ST(0));
      The above is exactly what you want. You need to make the other functions handle buf the same way this one does. You also got it correct for Net__LibnetRaw_libnet_build_ip and Net__LibnetRaw_libnet_build_tcp.
      XS(XS_Net__LibnetRaw_libnet_destroy_packet) [...] u_char * buf = (u_char *)SvPV(ST(0),PL_na); RETVAL = libnet_destroy_packet(&buf);
      You want to add some code here that destroys the buf object. Probably just:
      OUTPUT: buf sv_setsv(ST(0),&PL_sv_undef);
      Now for the source of your problem (I think):
      XS(XS_Net__LibnetRaw_libnet_init_packet) [...] u_char * buf = (u_char *)SvPV(ST(1),PL_na); [...] RETVAL = libnet_init_packet(p_size, &buf); sv_setpv((SV*)ST(1), buf);
      This function seems to have used a different typemap for buf which is trying to extract the '\0'-terminated string that it is supposed to point to. I think all you need to do is fix this typemap to be like the other functions.

      I'm going to check some other things I noticed and I'll reply separately if I detect any problems.

              - tye (but my friends call me "Tye")

      XS(XS_Net__LibnetRaw_libnet_write_ip) { dXSARGS; if (items != 3) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_write_ip(sock, + packet, len)"); { int sock = (int)SvIV(ST(0)); u_char * packet = (u_char *)SvPV(ST(1),PL_na); int len = (int)SvIV(ST(2)); int RETVAL; dXSTARG; RETVAL = libnet_write_ip(sock, packet, len); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); }
      I'd make len default to 0 (change "len" to "len=0" the first place it is mentioned) and add:
      INIT: if( 0 == len ) len= SvCUR(ST(1));
      so that write_ip($sock,$packet) works.

              - tye (but my friends call me "Tye")
        Ok. Here's what I tried, but libnet_build_ip() is still crapping. I understand what you said about making all the functions accept the same type at the end of your Re4. Some where accepting the buf itself and others a pointer to it even when my calls were using passing simply $buf each time. This is how I changed the XS file to fix this (I think) for the two functions in question:

        int libnet_init_packet(p_size, buf) size_t p_size u_char & buf CODE: u_char * buf_temp; buf_temp = &buf; RETVAL = libnet_init_packet(p_size, &buf_temp); OUTPUT: RETVAL buf int libnet_destroy_packet(buf) u_char & buf CODE: u_char * buf_temp; buf_temp = &buf; RETVAL = libnet_destroy_packet(&buf_temp); OUTPUT: RETVAL buf sv_setsv(ST(0),&PL_sv_undef);
        The resultant C code appears to hold the proper type for the passed in $buf now...
        XS(XS_Net__LibnetRaw_libnet_init_packet) { dXSARGS; if (items != 2) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_init_packet(p_ +size, buf)"); { size_t p_size = (size_t)SvIV(ST(0)); u_char buf = (u_char)SvUV(ST(1)); int RETVAL; dXSTARG; #line 39 "LibnetRaw.xs" u_char * buf_temp; buf_temp = &buf; RETVAL = libnet_init_packet(p_size, &buf_temp); #line 106 "LibnetRaw.c" sv_setuv(ST(1), (UV)buf); SvSETMAGIC(ST(1)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); } XS(XS_Net__LibnetRaw_libnet_destroy_packet) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Net::LibnetRaw::libnet_destroy_packet +(buf)"); { u_char buf = (u_char)SvUV(ST(0)); int RETVAL; dXSTARG; #line 50 "LibnetRaw.xs" u_char * buf_temp; buf_temp = &buf; RETVAL = libnet_destroy_packet(&buf_temp); #line 127 "LibnetRaw.c" sv_setsv(ST(0),&PL_sv_undef); SvSETMAGIC(ST(0)); XSprePUSH; PUSHi((IV)RETVAL); } XSRETURN(1); }
        So now, the type for buf passed in is u_char just like the other calls. I just noticed some other value vs. pointer to value mistakes I've made (It seems * and & are not quite as similar as I thought). That aside, I still think the error I am getting does not make sense.