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

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!

Replies are listed 'Best First'.
(tye)Re3: XS question: typemap for a pointer to a pointer?
by tye (Sage) on Apr 11, 2001 at 18:24 UTC

    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")
(tye)Re4: XS question: typemap for a pointer to a pointer?
by tye (Sage) on Apr 11, 2001 at 19:02 UTC

    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.

        No, you've made things worse. buf needs to always be u_char * or u_char * &. u_char & is completely different.

        Try again and/or reread what I wrote. You want $buf to hold an opaque UV that gets converted to/from a u_char *. Some of your calls should pass a reference to this u_char * rather than passing the u_char * directly (that is what the "&" is for). Those routines are the ones that might change the pointer (by allocating or reallocating the memory) and are also the ones that need buf mentioned in the OUTPUT: section.

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