XSUB detecting if it was called via Package->method() or Package::method()?

Discussion in 'Perl Misc' started by Chris, Nov 17, 2010.

  1. Chris

    Chris Guest

    So, if I call
    Package->method(),
    then the string "Package" will be the first item in @_ when inside the
    method() sub.

    If I call
    $object->method(),
    then $ will be the first item in @_ when inside the method() sub.

    If I call Package::method(), @_ will be empty.

    perldoc perlobj calls the first one a "class method", because it
    expects the class name as the first argument, and the second one an
    "instance method", because it expects an object reference as the first
    argument. The third one I consider a "static method", because it
    doesn't expect the first argument to be anything special.

    How can an XSUB differentiate between those 3?
    Chris, Nov 17, 2010
    #1
    1. Advertising

  2. Chris

    Uri Guttman Guest

    >>>>> "C" == Chris <> writes:

    C> So, if I call
    Package-> method(),
    C> then the string "Package" will be the first item in @_ when inside the
    C> method() sub.

    C> If I call
    C> $object->method(),
    C> then $ will be the first item in @_ when inside the method() sub.

    C> If I call Package::method(), @_ will be empty.

    C> perldoc perlobj calls the first one a "class method", because it
    C> expects the class name as the first argument, and the second one an
    C> "instance method", because it expects an object reference as the first
    C> argument. The third one I consider a "static method", because it
    C> doesn't expect the first argument to be anything special.

    the third one isn't a method at all. methods are ONLY called with the ->
    notation (or by indirect calls which you should avoid). the :: style is
    just a fully qualified sub name being called. no different than if you
    imported that sub or declared it locally. methods will use inheritence
    and the method name can be dynamically created. you can't do that with
    sub names without disabling strict. those are some major differences.

    C> How can an XSUB differentiate between those 3?

    check the first arg type should be easy enough but as with plain perl
    you should NEVER allow multiple call styles for a single sub. instance
    methods should only be called by objects, class methods via a package
    name and plain subs with neither of those. so your problem is solved,
    you don't need to know. it is up to the caller to make sure they do what
    you document.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Nov 18, 2010
    #2
    1. Advertising

  3. Chris

    Chris Guest


    > check the first arg type should be easy enough but as with plain perl
    > you should NEVER allow multiple call styles for a single sub.


    What if the sub is AUTOLOAD? If I have defined a sub called
    Package::AUTOLOAD, then Package->method('foo'), $package-
    >method('foo'), and Package::method('foo') will both redirect to the

    AUTOLOAD sub. AUTOLOAD then doesn't know if $_[0] is $self, the
    string 'Package', or the string 'foo'.
    Chris, Nov 18, 2010
    #3
  4. Chris

    Uri Guttman Guest

    >>>>> "C" == Chris <> writes:

    >> check the first arg type should be easy enough but as with plain perl
    >> you should NEVER allow multiple call styles for a single sub.


    C> What if the sub is AUTOLOAD? If I have defined a sub called
    C> Package::AUTOLOAD, then Package->method('foo'), $package-
    >> method('foo'), and Package::method('foo') will both redirect to the

    C> AUTOLOAD sub. AUTOLOAD then doesn't know if $_[0] is $self, the
    C> string 'Package', or the string 'foo'.

    but it knows the NAME of the sub. so it can dispatch based on that. a
    sub of a given name should only have one api style. it doesn't matter
    how the sub actually gets invoked but how you pass it args.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Nov 18, 2010
    #4
  5. Chris

    sisyphus Guest

    On Nov 18, 10:43 am, Chris <> wrote:

    > How can an XSUB differentiate between those 3?


    ########################################
    use warnings;
    use Math::BigInt;

    $x = Math::BigInt->new(100123);


    Math::BigInt->foo(42); # class
    $x->foo(42); # instance
    Math::BigInt::foo(42); # static

    package Math::BigInt;

    use Inline C => Config =>
    BUILD_NOISY=>1;

    use Inline C => <<'EOC';

    void foo(SV* x, ...) {
    dXSARGS;
    if(items == 1) printf("static method\n");
    else {
    if(SvPOK(ST(0))) {
    if(strEQ(SvPV_nolen(ST(0)), "Math::BigInt")) printf("class
    method\n");
    else printf("wtf?\n");
    }
    else printf("instance method\n");
    }
    XSRETURN(0);
    }

    EOC
    #########################################

    For me, after compiling, it prints:

    class method
    instance method
    static method

    Not entirely sure that the logic caters for all possibilities, but you
    should get the idea.

    When using ellipsis syntax with Inline::C you have to provide at least
    one argument - ie foo() must take at least one argument, and that's
    why I've provided a (fudge) argument of 42 ... and also why we have to
    check for items==1 (not items==0).

    In XS, I don't think that stipulation of "at least one arg" applies
    (though I don't really know for sure).

    Cheers,
    Rob
    sisyphus, Nov 18, 2010
    #5
  6. Chris

    Uri Guttman Guest

    >>>>> "s" == sisyphus <> writes:

    s> Not entirely sure that the logic caters for all possibilities, but you
    s> should get the idea.

    and if you read my reply, you will see that this is a big mistake. one
    sub should not be called with different apis. the whole question is
    wrong.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Nov 18, 2010
    #6
  7. Chris

    Chris Guest

    Let me put this in a little more context.

    I'm writing Perl bindings to Qt. So, there's a lot of methods,
    including method overloading. So, for instance, in C++ you can write
    QApplication app(argc, argv);
    QObject::connect( &app, SIGNAL(aboutToQuit()), &app,
    SLOT(quit()) );

    or you could write
    QApplication app(argc, argv);
    app.connect( &app, SIGNAL(aboutToQuit()), &app, SLOT(quit()) );

    Both forms are valid, and I'd like for both forms to be valid in Perl,
    too.

    In my Perl bindings, every method call goes through 1 AUTOLOAD sub.
    From the information in the AUTOLOAD sub, I have to determine the
    correct C++ method to call. The only reliable information is the
    $AUTOLOAD variable, which tells me 1) the name of the method being
    called and 2) the package that method is in. The other information I
    need to know is how many arguments were passed. Unfortunately,
    because $_[0] (or, since I'm in XS, ST(0)), may be the object doing
    the call, I can't rely on the "items" variable. It might be 1 more
    than the number of arguments passed, it might not.



    Let's say I have the following C++ methods:
    static QObject::doSomethingWith( QObject*, QObject* );
    QObject::doSomethingWith( QObject* );

    to call those methods in Perl I'd write:
    QObject::doSomethingWith( $object1, $object2 );
    $object1->doSomethingWith( $object2 );

    Then in AUTOLOAD I get the same information for both methods:
    $AUTOLOAD = 'QObject::doSomethingWith'
    @_ = ( $object1, $object2 )

    If I could differentiate between the instance method ("$object1-
    >doSomethingWith") and the "static" method

    ("QObject::doSomethingWith"), then I could determine the correct C++
    method to call.

    I do have a workaround for this, but it's pretty hack-tastic, and I'm
    trying to see if there's a cleaner solution. But it's looking like
    Perl doesn't supply me with the information I'm looking for.
    Chris, Nov 18, 2010
    #7
  8. Chris

    sisyphus Guest

    On Nov 18, 1:58 pm, "Uri Guttman" <> wrote:
    > >>>>> "s" == sisyphus  <> writes:

    >
    >   s> Not entirely sure that the logic caters for all possibilities, butyou
    >   s> should get the idea.
    >
    > and if you read my reply, you will see that this is a big mistake. one
    > sub should not be called with different apis. the whole question is
    > wrong.


    Yes, I've read your reply.

    Cheers,
    Rob
    sisyphus, Nov 18, 2010
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    296
    Alan Johnson
    Feb 1, 2007
  2. Hartin, Brian
    Replies:
    1
    Views:
    93
    Jacob Fugal
    Nov 10, 2006
  3. Jeff

    XS/XSUB FAQs? Tutorials?

    Jeff, Sep 25, 2003, in forum: Perl Misc
    Replies:
    2
    Views:
    82
    Anno Siegel
    Sep 26, 2003
  4. Andrew Torda
    Replies:
    16
    Views:
    169
  5. thorsten kracht

    xsub and gcc 4.0.2, static variables

    thorsten kracht, Mar 6, 2006, in forum: Perl Misc
    Replies:
    1
    Views:
    81
    Anno Siegel
    Mar 6, 2006
Loading...

Share This Page