Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl XS and C++ passing pointer to buffer

Tags:

perl

xs

I know almost no C++ so that's not helping, and my XS isn't much better. I'm creating an XS interface for a C++ library and I have almost all my methods working except one.

The method in Perl should look like this:

$return_data = $obj->readPath( $path );

The method is defined as this the .h file:

int readPath(const char* path, char* &buffer, bool flag=true);

The "buffer" will get allocated if it's passed in NULL.

There's two additional versions of readPath with different signatures, but they are not the ones I want. (And interestingly, when I try and compile it tells me the "candidates" are the two I don't want.) Is that because it's not understanding the "char * &"?

Can someone help with the xsub I need to write?

I'm on Perl 5.14.2.

BTW -- I've also used a typemap "long long int" to T_IV. I cannot find any documentation on how to correctly typemap long long. Any suggestions how I should typemap long long?

Thanks,

like image 919
user1446426 Avatar asked Oct 08 '22 04:10

user1446426


2 Answers

I've never dealt with C++ from C or XS. If it was C, it would be:

void
readPath(SV* sv_path)
   PPCODE:
      {
         char*  path   = SvPVbyte_nolen(sv_path, len);
         char*  buffer = NULL;

         if (!readPath(path, &buffer, 0))
            XSRETURN_UNDEF;

         ST(0) = sv_2mortal(newSVpv(buffer, 0));
         free(buffer);

         XSRETURN(1);
      }

Hopefully, that works or you can adjust it to work.


I assumed:

  • readPath returns true/false for success/failure.
  • buffer isn't allocated on failure.
  • The deallocator for buffer is free.
like image 89
ikegami Avatar answered Nov 09 '22 18:11

ikegami


Second part of the question is TYPEMAP for long long (or long long int).

Normally long is at least 32 bits and long long is at least 64. The default typemap for long is T_IV. Perl's equivalent for long long is T_IV, too.

But sometimes, you wan't to reduce warnings for cast. So, you can use T_LONG for long. T_LONG is an equivalent to T_IV but explicitly casts the return to type long. The TYPEMAP for T_LONG is descripted at $PERLLIB/ExtUtils/typemap

With this knowledge you can write you own TYPEMAP for long long int:

TYPEMAP: <<TYPEMAPS
long long int T_LONGLONG

INPUT
T_LONGLONG
  $var = (long long int)SvIV($arg)

OUTPUT
T_LONGLONG
  sv_setiv($arg, (IV)$var);
TYPEMAPS
like image 24
brickpool Avatar answered Nov 09 '22 20:11

brickpool