Affix

 view release on metacpan or  search on metacpan

t/001_affix.t  view on Meta::CPAN

        b    => UInt32, 16,    # b : uint32 : 16
        c    => UInt32, 16,    # c : uint32 : 16
        d    => UInt32, 16,    # d : uint32 : 16
        tail => UInt8          # tail : uint8
    ];
    isa_ok my $check = wrap( $lib_path, 'check_trailing', [$trailing] => UInt8 ), ['Affix'];
    is $check->( { a => 1, b => 2, c => 3, d => 4, tail => 0x5A } ), 0x5A, 'd (bit offset 16) marshals without disturbing the following member';
    is $check->( { a => 0xFFFF, b => 0xFFFF, c => 0xFFFF, d => 0xFFFF, tail => 0x5A } ), 0x5A,
        'max-value d (bit offset 16) marshals without disturbing the following member';
};
subtest 'Forward Call with Many Arguments' => sub {
    note 'Testing a C function with more arguments than available registers.';
    my $sig = '(int64, int64, int64, int64, int64, int64, int64, int64, int64)->int64';
    isa_ok my $summer = wrap( $lib_path, 'multi_arg_sum', $sig ), ['Affix'];
    my $result = $summer->( 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 );
    is $result, 111111111, 'Correctly passed 9 arguments to a C function';
};
subtest 'Parser Error Reporting' => sub {
    note 'Testing that malformed signatures produce helpful error messages.';
    like warning { Affix::wrap( $lib_path, 'add', '(int, ^, int)->int' ) }, qr[parse signature], 'wrap() warning on invalid signature';
    like warning { Affix::sizeof('{int, double') },                         qr[parse signature], 'sizeof() warning on unterminated aggregate';
};
subtest 'These are called under valgrind in 900_leak' => sub {
    subtest 'use Affix' => sub {
        use Affix qw[];
        pass 'loaded';
    };
    subtest 'affix($$$$)' => sub {
        no warnings 'redefine';
        ok affix( libm, 'pow', [ Double, Double ], Double ), 'affix pow( Double, Double )';
        is pow( 5, 2 ), 25, 'pow(5, 2)';
    };
    subtest 'wrap($$$$)' => sub {
        isa_ok my $pow = wrap( libm, 'pow', [ Double, Double ], Double ), ['Affix'], 'double pow(double, double)';
        is $pow->( 5, 2 ), 25, '$pow->(5, 2)';
    };
    subtest 'return pointer' => sub {
        my $lib = compile_ok(<<'');
#include "std.h"
// ext: .c
void * test( ) { void * ret = "Testing"; return ret; }

        ok my $fn         = wrap( $lib, 'test', [] => Pointer [Void] ), 'affix';
        ok my $string_ptr = $fn->(),                                    'call';

        # Casting a pointer to String should return the Value "Testing"
        is Affix::cast( $string_ptr, String ), 'Testing', 'cast($ptr, String) returns value';
    }
};
subtest 'affix/wrap function pointer' => sub {
    my $lib = compile_ok(<<~'');
    #include "std.h"
    //ext: .c
    DLLEXPORT int add(int a, int b) { return a + b; }


    # Get address via find_symbol (simulating getting it from vtable or dlsym)
    my $ptr = find_symbol( load_library($lib), 'add' );
    ok $ptr, 'Got function pointer';

    # Test wrap(undef, $ptr, ...)
    subtest 'wrap(undef, $ptr, ...)' => sub {
        my $fn = wrap( undef, $ptr, [ Int, Int ] => Int );
        is $fn->( 10, 20 ), 30, 'Wrapped raw function pointer works';
    };

    # Test affix(undef, [$ptr => 'name'], ...)
    subtest 'affix(undef, [$ptr => name], ...)' => sub {
        affix( undef, [ $ptr => 'my_add' ], [ Int, Int ] => Int );
        is my_add( 5, 5 ), 10, 'Affixed raw function pointer works';
    };

    # Test wrap with explicit raw integer (simulating cast)
    subtest 'wrap(undef, int_addr, ...)' => sub {
        my $addr = address($ptr);                               # Convert Pin to UV
        my $fn   = wrap( undef, $addr, [ Int, Int ] => Int );
        is $fn->( 3, 4 ), 7, 'Wrapped raw integer address works';
    };
};
#
done_testing;



( run in 1.272 second using v1.01-cache-2.11-cpan-d80b1682f3f )