In XS I can pass the length of a string argument to a C function using the length keyword:
static int foo(const char *s, size_t len)
{
return 1;
}
MODULE = Foo PACKAGE = Foo
void
foo(char *s, STRLEN length(s))
However how can I get the length of the string if I need it inside the CODE block?
void
foo(char *s, STRLEN length(s))
CODE:
...
foo(s, ???);
I can use STRLEN_length_of_s
or XSauto_length_of_s
variable autogenerated
by xsubpp but it feels a bit hardcoded. Is there a way (possibly a predefined macro) I can use to get the variable name? Or can I assign my own name to the length argument? Or do I need to resort to declaring the argument as SV *
and then get the length myself with SvPV
in CODE section?
First of all, if you're using char*
in your XS prototype (and the default typemap), your code is buggy.
You want
void
foo(SV* sv)
PREINIT:
STRLEN len;
char* s;
CODE:
s = SvPVbyte(sv, len);
foo(s, len);
or
void
foo(SV* sv)
PREINIT:
STRLEN len;
char* s;
CODE:
s = SvPVutf8(sv, len);
foo(s, len);
Remember that Perl strings are sequences of 32-bit or 64-bit numbers, while C strings are sequences of 8-bit chars.[1] Some conversion needs to occur, and you need to specify which one.
In the first case, each character of the string will be a char
of s
.
In the second case, s
will be provided the Perl string encoded using utf8.
char
can be larger than 8 bits, but I don't think it can be on systems supported by perl
.