#859 SWIG_AsCharPtrAndSize() for all Perl scalars - not just stri

closed-accepted
perl (97)
5
2007-12-12
2007-09-20
No

Mappings from Perl values to "char *" typically use SWIG_AsCharPtrAndSize(). But at the moment this function fails if you call it with e.g. a number instead of a string.

This can be fixed if the initial "if (SvPOK(obj)) {" in SWIG_AsCharPtrAndSize() is changed to "if (SvOK(obj)) {". Then the following SvPV(obj, len) will take care of coercing all types of scalars to the required string.

But maybe there is a reason for using SvPOK() instead of SvOK(), which I just haven't understood?

Discussion

  • Olly Betts

    Olly Betts - 2007-10-25
    • labels: --> perl
     
  • William Fulton

    William Fulton - 2007-12-12

    Logged In: YES
    user_id=242951
    Originator: NO

    We don't have an active Perl maintainer, but this suggestion seems reasonable, so I've applied it for 1.3.34.

     
  • William Fulton

    William Fulton - 2007-12-12
    • assigned_to: nobody --> wsfulton
    • status: open --> closed-accepted
     
  • William Fulton

    William Fulton - 2007-12-16

    Logged In: YES
    user_id=242951
    Originator: NO

    This patch has been removed due Josh Cherry comments posted on swig-user...

    I see potential problems with this change, though I'm now somewhat confused about SWIG's char* handling (I mostly deal with std::string):

    1. It changes the behavior when the argument is an actual wrapped char pointer, which is what the "else" branch was supposed to handle (I don't think the "else" branch will now ever execute, except in cases where it will fail). This could be fixed by trying the SWIG_ConvertPtr *first*.

    2. With the change, things like wrapped int* and proxy class instances will be accepted as char*, whereas they were not accepted before. Arguably this is the correct behavior, but maybe it is undesirable.

    Consideration of (1) led to my confusion about char*. char* is treated differently from other pointers to built-in types (e.g., int*). Among other issues, this treatment means that obtaining an actual wrapped char* takes some work. It's easy enough to do with a typemap, and it's often useful to have a real pointer rather than a copy of the string.

    Anyway, the following illustrates points 1 and 2:

    %module aa

    %inline %{

    #include <stdio.h>

    char *aa_string = "Is mah string";

    void print_str(char *str) {
    printf("%s\n", str);
    }

    struct Foo {
    };

    int *iptr;

    #ifdef SWIG
    %typemap(out) char * = SWIGTYPE *; /* affects return_ptr */
    #endif
    char *return_ptr(void) {
    return aa_string;
    }

    %}

    Before the change to SWIG:

    aa::print_str(aa::return_ptr());
    Is mah string

    aa::print_str($aa::iptr);
    TypeError in method 'print_str', argument 1 of type 'char *'

    aa::print_str(new aa::Foo());
    TypeError in method 'print_str', argument 1 of type 'char *'

    After the change:

    aa::print_str(aa::return_ptr());
    _p_char=SCALAR(0x814fd90)

    aa::print_str($aa::iptr);
    _p_int=SCALAR(0x83d6b98)

    aa::print_str(new aa::Foo());
    aa::Foo=HASH(0x837b6fc)

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks