Affix

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

by [Raku's `native` trait](https://docs.raku.org/language/nativecall).

A simple example would look like this:

```perl
use Affix;
sub some_argless_function :Native('something');
some_argless_function();
```

The first line imports various code attributes and types. The next line looks
like a relatively ordinary Perl sub declaration--with a twist. We use the
`:Native` attribute in order to specify that the sub is actually defined in a
native library. The platform-specific extension (e.g., .so or .dll), as well as
any customary prefixes (e.g., lib) will be added for you.

The first time you call "some\_argless\_function", the "libsomething" will be
loaded and the "some\_argless\_function" will be located in it. A call will then
be made. Subsequent calls will be faster, since the symbol handle is retained.

Of course, most functions take arguments or return values--but everything else

README.md  view on Meta::CPAN

    ],                          } dob;
    name => Str,                char *name;
    wId  => Long                long wId;
];                          };
```

A struct consists of a sequence of members with storage allocated in an ordered
sequence (as opposed to `Union`, which is a type consisting of a sequence of
members where storage overlaps).

A C struct that looks like this:

```
struct {
    char *make;
    char *model;
    int   year;
};
```

...would be defined this way:

README.md  view on Meta::CPAN


A union is a type consisting of a sequence of members with overlapping storage
(as opposed to `Struct`, which is a type consisting of a sequence of members
whose storage is allocated in an ordered sequence).

The value of at most one of the members can be stored in a union at any one
time and the union is only as big as necessary to hold its largest member
(additional unnamed trailing padding may also be added). The other members are
allocated in the same bytes as part of that largest member.

A C union that looks like this:

```
union {
    char  c[5];
    float f;
};
```

...would be defined this way:

dyncall/ToDo  view on Meta::CPAN

- find big endian arm box (also hardfloat), e.g. cubietruck: http://blog.netbsd.org/tnf/entry/working_arm_multiprocessor_support
- test if armhf/thumb is actually working... pulls in arm mode code in dyncall_callvm.c
- dyncall_call_mips_n32.h and dyncall_call_mips_n64.h are pretty much the same, share code
- support for return values: aggregate return values on non-x64
- support for argument values: aggregates on non-x64, vector types, long double (c89)
  * make sure that struct support for ellipsis calls are not forgotten (copy everything by value)
- support for argument values: _Complex (c99)
- support for argument values: Fixed-width integer types (c99) - could be just aliases but would help abstracting it away from library users
- other syscalls
- test MIPS32 eabi big endian (current port works on psp, which is little endian)
- implement MIPS64 N32 (gcc -mabi=n32); both, little and big-endian (looks like NetNBSD on and
  EdgeRouter lite uses this: https://blog.netbsd.org/tnf/entry/hands_on_experience_with_edgerouter)
- MIPS64 n32 softfloat support (-msoft-float)
- implement MIPS64 EABI (gcc -mabi=eabi); both, little and big-endian
- support for Minix/arm
- improve ellipsis test:
  * test not just with one fixed arg, to also simulate alignment problems
  * test return values
  * convert from c++ to c, to have it also on plan9, and more portability

dynload:

dyncall/ToDo  view on Meta::CPAN

    dynload_syms_elf.c:164: error: `DT_SYMTAB' undeclared (first use in this function)
    dynload_syms_elf.c:165: error: `DT_HASH' undeclared (first use in this function)
    make: *** [dynload_syms.o] Error 1

dyncallback:
------------
- callback_plain's return value not correct anymore on NDS (maybe just broken testcode?),
  see above under 1.1 items
  * check other platforms also, if asm stub initializes retval space, correctly
- test MIPS32 eabi big endian (current port works on psp, which is little endian)
- implement MIPS64 N32 (gcc -mabi=n32); both, little and big-endian (looks like NetNBSD on and
  EdgeRouter lite uses this: https://blog.netbsd.org/tnf/entry/hands_on_experience_with_edgerouter)
- MIPS64 n32 softfloat support (-msoft-float)
- implement MIPS64 EABI (gcc -mabi=eabi); both, little and big-endian
- support for Minix/arm

bindings:
---------
- release bindings as standalone packages (already done for rbdc as a gem and rdyncall on cran)
  * add note to documentation, where bindings are
- add rdoc documentation to ruby gem

dyncall/doc/disas_examples/x86.plan9call.disas  view on Meta::CPAN

0010b0   c7042400000000       (16)      MOVL                        $0,(SP)            ; arg 0 -> "push" onto stack
0010b7   b801000000           (16)      MOVL                        $1,AX              ; arg 1 -> eax, then ...
0010bc   89442404             (16)      MOVL                        AX,4(SP)           ; ... "pushed" onto stack
0010c0   b802000000           (16)      MOVL                        $2,AX              ; arg 2 -> eax, then ...
0010c5   89442408             (16)      MOVL                        AX,8(SP)           ; ... "pushed" onto stack
0010c9   b803000000           (16)      MOVL                        $3,AX              ;    .
0010ce   8944240c             (16)      MOVL                        AX,12(SP)          ;    .
0010d2   b804000000           (16)      MOVL                        $4,AX              ;    .
0010d7   89442410             (16)      MOVL                        AX,16(SP)          ;    .
0010db   8d442414             (16)      LEAL                        20(SP),AX          ; get ptr to next (unused) stack bytes -> eax ...
0010df   89442430             (16)      MOVL                        AX,.safe+48(SP)    ; ... and write it to very top of stack (seems aligned and not adjacent to last arg)    | looks like callconv keeps a ptr to
0010e3   8b442430             (16)      MOVL                        .safe+48(SP),AX    ; regetting of same ptr into eax (pointless as same as in eax)                          | each struct params in local area
0010e7   c70005000000         (16)      MOVL                        $5,(AX)            ; |
0010ed   8b442430             (16)      MOVL                        .safe+48(SP),AX    ; |
0010f1   c7400406000000       (16)      MOVL                        $6,4(AX)           ; | copy struct linearly to stack, adjacent to other args
0010f8   8b442430             (16)      MOVL                        .safe+48(SP),AX    ; |
0010fc   c7400807000000       (16)      MOVL                        $7,8(AX)           ; |
001103   c7400c00000000       (16)      MOVL                        $0,12(AX)          ; |                    msbytes of long long
00110a   b808000000           (16)      MOVL                        $8,AX              ; arg 6 -> eax, then ...
00110f   89442424             (16)      MOVL                        AX,36(SP)          ; ... "pushed" onto stack
001113   b809000000           (16)      MOVL                        $9,AX              ; arg 7 -> eax, then ...

lib/Affix.pm  view on Meta::CPAN


All the sugar is right here in the :Native code attribute. This API is inspired
by L<Raku's C<native> trait|https://docs.raku.org/language/nativecall>.

A simple example would look like this:

    use Affix;
    sub some_argless_function :Native('something');
    some_argless_function();

The first line imports various code attributes and types. The next line looks
like a relatively ordinary Perl sub declaration--with a twist. We use the
C<:Native> attribute in order to specify that the sub is actually defined in a
native library. The platform-specific extension (e.g., .so or .dll), as well as
any customary prefixes (e.g., lib) will be added for you.

The first time you call "some_argless_function", the "libsomething" will be
loaded and the "some_argless_function" will be located in it. A call will then
be made. Subsequent calls will be faster, since the symbol handle is retained.

Of course, most functions take arguments or return values--but everything else

lib/Affix.pm  view on Meta::CPAN

            day   => Int                int day;
        ],                          } dob;
        name => Str,                char *name;
        wId  => Long                long wId;
    ];                          };

A struct consists of a sequence of members with storage allocated in an ordered
sequence (as opposed to C<Union>, which is a type consisting of a sequence of
members where storage overlaps).

A C struct that looks like this:

    struct {
        char *make;
        char *model;
        int   year;
    };

...would be defined this way:

    Struct[

lib/Affix.pm  view on Meta::CPAN


A union is a type consisting of a sequence of members with overlapping storage
(as opposed to C<Struct>, which is a type consisting of a sequence of members
whose storage is allocated in an ordered sequence).

The value of at most one of the members can be stored in a union at any one
time and the union is only as big as necessary to hold its largest member
(additional unnamed trailing padding may also be added). The other members are
allocated in the same bytes as part of that largest member.

A C union that looks like this:

    union {
        char  c[5];
        float f;
    };

...would be defined this way:

    Union[
        c => ArrayRef[Char, 5],

lib/Affix.xs  view on Meta::CPAN

#define GvNAMELEN_get GvNAMELEN
#endif

#ifndef CvGV_set
#define CvGV_set(cv, gv) (CvGV(cv) = (gv))
#endif

/* general utility */

#if PERL_BCDVERSION >= 0x5008005
#define LooksLikeNumber(x) looks_like_number(x)
#else
#define LooksLikeNumber(x) (SvPOKp(x) ? looks_like_number(x) : (I32)SvNIOKp(x))
#endif

// added in perl 5.35.7?
#ifndef sv_setbool_mg
#define sv_setbool_mg(sv, b) sv_setsv_mg(sv, boolSV(b))
#endif

#define newAV_mortal() (AV *)sv_2mortal((SV *)newAV())
#define newHV_mortal() (HV *)sv_2mortal((SV *)newHV())
#define newRV_inc_mortal(sv) sv_2mortal(newRV_inc(sv))

lib/Affix.xs  view on Meta::CPAN

        /* Int->sig == 'i'; Struct[Int, Float]->sig == '{if}' */                                   \
        cv = newXSproto_portable(form("%s::sig", package), Types_sig, file, "$");                  \
        XSANY.any_i32 = (int)SIGCHAR;                                                              \
        /* embed an extra character inside a method call to get the 'real' C type*/                \
        cv = newXSproto_portable(form("%s::csig", package), Types_sig, file, "$");                 \
        XSANY.any_i32 = (int)SIGCHAR_C;                                                            \
        /* types objects can stringify to sigchars */                                              \
        cv = newXSproto_portable(form("%s::(\"\"", package), Types_sig, file, ";$");               \
        XSANY.any_i32 = (int)SIGCHAR;                                                              \
        /* The magic for overload gets a GV* via gv_fetchmeth as */                                \
        /* mentioned above, and looks in the SV* slot of it for */                                 \
        /* the "fallback" status. */                                                               \
        sv_setsv(get_sv(form("%s::()", package), TRUE), &PL_sv_yes);                               \
        /* Making a sub named "Affix::Call::Aggregate::()" allows the package */                   \
        /* to be findable via fetchmethod(), and causes */                                         \
        /* overload::Overloaded("Affix::Call::Aggregate") to return true. */                       \
        (void)newXSproto_portable(form("%s::()", package), Types_sig, file, ";$");                 \
    }

#define CLEANUP(NAME)                                                                              \
    cv = get_cv(form("Affix::%s", #NAME), 0);                                                      \



( run in 0.529 second using v1.01-cache-2.11-cpan-64827b87656 )