Beefy Boxes and Bandwidth Generously Provided by pair Networks vroom
Think about Loose Coupling
 
PerlMonks  

Re^2: Can't create XSUBs for C functions with a same name

by davido (Archbishop)
on Aug 23, 2012 at 21:00 UTC ( #989382=note: print w/ replies, xml ) Need Help??


in reply to Re: Can't create XSUBs for C functions with a same name
in thread Can't create XSUBs for C functions with a same name

Let's say the user has two (or more) functions that are overloaded (C++ obviously), and that it's not trivial to implement them as a single variable-parameter function. Obviously XS can't deal with overloaded functions -- it's just too much a C++ thing. But there is another hope, and one that's often used when using Inline::C or Inline::CPP to interface with external libraries: Write a wrapper function.

Another limitation of Inline::CPP is that you can't expose templates directly to Perl. As with function overloading, Perl XS would have no idea what to do with template definitions. And C++ wouldn't know how Perl intends to call the functions, and thus wouldn't be able to expand the templates at compile-time. But once again, simple wrappers can easily hide templates from Perl/XS.

Ok, we're not dealing with templates here... just overloading. Either way the following will work. Write a wrapper that accepts a variable argument list, and then dispatches a call to the overloaded functions based on how many args are provided. It's a little cumbersome once you get more than a handful of variations to deal with, but I don't think people generally create more than a handful of overloads anyway (they just turn to templates, which is why I mentioned templates earlier).

So here's a hybrid: The overloaded functions (which won't bind to Perl), and the wrapper (which will):

use strict; use warnings; use v5.16; use Inline CPP => 'DATA'; say multiadd( 1 ); # No dispatch; just return the value. say multiadd( 1, 2 ); # Dispatch add( int, int ). say multiadd( 1, 2, 3 ); # Dispatch add( int, int, int ). say multiadd( 1, 2, 3, 4 ); # No dispatch; throw an exception. __DATA__ __CPP__ #include <stdexcept> // Overloaded functions: add(int,int), add(int,int,int): No (reliable* +) Perl binding. int add ( int a, int b ) { return a + b; } int add ( int a, int b, int c ) { return a + b + c; } // XS binding will be generated for multiadd(). int multiadd ( SV * a, ... ) { dXSARGS; try{ switch ( items ) { case 1: return SvIV(ST(0)); case 2: return add( SvIV(ST(0)), SvIV(ST(1)) ); case 3: return add( SvIV(ST(0)), SvIV(ST(1)), SvIV(ST(2)) ); default: throw std::runtime_error( "multiadd() - Too many args in function call" ); } } catch ( std::runtime_error msg ) { croak( msg.what() ); // Perl wants exceptions via croak. } }

This same approach could be used to dispatch calls based on any function signature criteria; number of parameters, or data-types. Additionally, a similar approach works for dispatching to template-generated functions or classes.

*(reliable): I think the last overload defined will bind via XS, but the others will be masked. It's not worth even trying to call directly.


Dave


Comment on Re^2: Can't create XSUBs for C functions with a same name
Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://989382]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (3)
As of 2014-04-20 21:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (487 votes), past polls