Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re: Passing integer pointer in XS?

by ikegami (Patriarch)
on Jul 18, 2016 at 20:23 UTC ( [id://1167993]=note: print w/replies, xml ) Need Help??


in reply to Passing integer pointer in XS?

Provides the specified interface:

#define _MAX_PROTOCOL_LEN 25 #define _MAX_MODEL_LEN 25 int tdSensor(SV* protocol_sv, SV* model_sv, SV* id_sv, SV* dataTypes_sv) CODE: { char protocol[_MAX_PROTOCOL_LEN + 1]; char model[_MAX_MODEL_LEN + 1]; int id; int dataTypes; RETVAL = tdSensor( protocol, sizeof(protocol), model, sizeof(model), &id, &dataTypes ); if (RETVAL == TELLSTICK_SUCCESS) { SV* sv; sv = sv_2mortal(newSVpv(protocol, 0))); SvSetMagicSV(protoco +l_sv, sv); sv = sv_2mortal(newSVpv(model, 0)); SvSetMagicSV(model_s +v, sv); sv = sv_2mortal(newIV(id)); SvSetMagicSV(id_sv, + sv); sv = sv_2mortal(newIV(dataTypes)); SvSetMagicSV(dataTyp +es_sv, sv); } else { SvSetMagicSV(protocol_sv, &PL_sv_undef); SvSetMagicSV(model_sv, &PL_sv_undef); SvSetMagicSV(id_sv, &PL_sv_undef); SvSetMagicSV(dataTypes_sv, &PL_sv_undef); } } OUTPUT: RETVAL

Untested.


Provides a more Perlish interface:

#define _MAX_PROTOCOL_LEN 25 #define _MAX_MODEL_LEN 25 SV* tdSensor() CODE: { char protocol[_MAX_PROTOCOL_LEN + 1]; char model[_MAX_MODEL_LEN + 1]; int id; int dataTypes; int rv = tdSensor( protocol, sizeof(protocol), model, sizeof(model), &id, &dataTypes ); if (rv == TELLSTICK_SUCCESS) { HV* hv = newHV(); SV* sv; /* In theory, hv_stores can fail. */ /* However, I suspect it can't happen for this new hash. */ /* It it were to happen here, this code would leak. */ sv = newSVpv(protocol, 0); hv_stores(hv, "protocol", sv); sv = newSVpv(model, 0); hv_stores(hv, "model", sv); sv = newIV(id); hv_stores(hv, "id", sv); sv = newIV(dataTypes); hv_stores(hv, "dataTypes", sv); RETVAL = newRV_noinc(MUTABLE_SV(hv)); } else { RETVAL = &PL_sv_undef; } } OUTPUT: RETVAL

Usage:

use feature qw( say ); while (my $rec = tdSensor()) { say join ', ', "protocol: $rec->{protocol}", "model: $rec->{model}", "sensorId: $rec->{id}", "dataTypes: $rec->{dataTypes}"; }

Untested.

Update: Fixed missing sv declaration and missing typecast for newRV_noinc's argument.

Replies are listed 'Best First'.
Re^2: Passing integer pointer in XS?
by martin67 (Novice) on Jul 18, 2016 at 20:56 UTC
    Thank you! This looks interesting - and definately a new area of Perl for me... I tried to compile it but ran into an error:
    TellStick.xs:70:10: error: ‘sv’ undeclared (first use in this function +)
    I guess sv needs to be declared. And there was a typo for NewSViv. So now it looks like
    if (rv == TELLSTICK_SUCCESS) { HV* hv = newHV(); SV *sv = newSV(0); sv = newSVpv(protocol, 0); hv_stores(hv, "protocol", sv); sv = newSVpv(model, 0); hv_stores(hv, "model", sv); sv = newSViv(id); hv_stores(hv, "id", sv); sv = newSViv(dataTypes); hv_stores(hv, "dataTypes", sv); RETVAL = newRV_noinc(hv); } else { RETVAL = &PL_sv_undef; }
    There were some compilation warnings as well, don't know if they are important:
    In file included from /usr/lib/arm-linux-gnueabihf/perl/5.20/CORE/perl +.h:5102:0, from TellStick.xs:2: TellStick.xs: In function ‘XS_TellStick_tdSensor’: TellStick.xs:76:31: warning: passing argument 2 of ‘Perl_newRV_noinc’ +from incompatible pointer type RETVAL = newRV_noinc(hv); ^ /usr/lib/arm-linux-gnueabihf/perl/5.20/CORE/embed.h:371:48: note: in d +efinition of macro ‘newRV_noinc’ #define newRV_noinc(a) Perl_newRV_noinc(aTHX_ a) ^ In file included from /usr/lib/arm-linux-gnueabihf/perl/5.20/CORE/perl +.h:5061:0, from TellStick.xs:2: /usr/lib/arm-linux-gnueabihf/perl/5.20/CORE/proto.h:2874:19: note: exp +ected ‘struct SV * const’ but argument is of type ‘struct HV *’ PERL_CALLCONV SV* Perl_newRV_noinc(pTHX_ SV *const sv)
    But the code works!!!

    I get the correct values:

    protocol: mandolyn, model: temperaturehumidity, sensorId: 51, dataType +s: 3 protocol: mandolyn, model: temperaturehumidity, sensorId: 61, dataType +s: 3
    Thank you very much for your help! Now I have a way forward for implementing the rest of fucntion in the C library.

      This is the kind of code that, in my experience, is one of the most likely sources of particularly troublesome errors/bugs. If you want to provide a Perlish interface, then I'd implement that in Perl code, not in XS code.

      If you are having to deal with reference counts, for example, then you are highly likely to get it wrong sooner rather than later and more than once and probably not always notice the problem before you release the code.

      Just write a tiny wrapper function in mundane Perl code and have that call the very, very thinly wrapped XS that calls the C code. Only do in XS those things that you really have to do in XS.

      - tye        

        What would be simpler than returning them in a hash? ...oh yeah, returning them in a list! Here ya go.
        void tdSensor() CODE: { char protocol[_MAX_PROTOCOL_LEN + 1]; char model[_MAX_MODEL_LEN + 1]; int id; int dataTypes; int rv = tdSensor( protocol, sizeof(protocol), model, sizeof(model), &id, &dataTypes ); if (rv != TELLSTICK_SUCCESS) { XSRETURN(0); } EXTEND(SP, 4); ST(0) = sv_2mortal(newSVpv(protocol, 0))); ST(1) = sv_2mortal(newSVpv(model, 0)); ST(2) = sv_2mortal(newIV(id)); ST(3) = sv_2mortal(newIV(dataTypes)); XSRETURN(4); }

        Usage:

        use feature qw( say ); while (my ($protocol, $model, $id, $dataTypes) = tdSensor()) { say join ', ', "protocol: $protocol", "model: $model", "sensorId: $id", "dataTypes: $dataTypes"; }

        Untested.

      SV *sv = newSV(0); leaks. You want SV *sv;

      The other issue is because I forgot to cast it. newRV_noinc(hv) should be newRV_noinc(MUTABLE_SV(hv)).

      Fixed in original.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (8)
As of 2024-04-16 11:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found