Affix
view release on metacpan or search on metacpan
t/092_struct_signature_layout.t view on Meta::CPAN
use v5.40;
use lib '../lib', 'lib';
use blib;
use Test2::Tools::Affix qw[:all];
use Test2::V0 -no_srand => 1;
use Affix qw[:all];
#
# Regression test for struct member layout when a struct type is declared
# inline in a function signature (as opposed to a typedef-registered type).
#
# Structs inside function signatures used to keep the offsets computed at
# parse time, while their members were still unresolved named types (size 0).
# The layout-recalc pass (Layout stage) never descended into function
# signatures, so every member ended up at the same offset. Bindings such as
# libpng's `png_image_write_to_file` then read/wrote members at the wrong
# bytes (version read back as 0, libpng complained about the struct layout).
#
# The struct below mirrors png_image's shape: a leading member that pushes
# the following scalar fields off offset 0, and fields typed through a named
# type so they are unresolved until the Resolve stage.
my $c_source = <<'END_C';
#include "std.h"
//ext: .c
#include <stdbool.h>
#include <stddef.h>
typedef unsigned int png_uint_32;
typedef struct {
void * opaque;
png_uint_32 version;
png_uint_32 width;
png_uint_32 height;
png_uint_32 format;
png_uint_32 flags;
} png_image;
DLLEXPORT bool set_image(png_image * out, png_uint_32 version, png_uint_32 width,
png_uint_32 height, png_uint_32 format, png_uint_32 flags) {
if (!out)
return false;
out->version = version;
out->width = width;
out->height = height;
out->format = format;
out->flags = flags;
return true;
}
DLLEXPORT bool check_image(const png_image * in) {
if (!in)
return false;
return in->version == 1 && in->width == 2 && in->height == 3 && in->format == 4 && in->flags == 5;
}
DLLEXPORT size_t image_sizeof(void) { return sizeof(png_image); }
END_C
#
my $lib = compile_ok($c_source);
ok( $lib, "Library compiled at $lib" );
#
( run in 0.491 second using v1.01-cache-2.11-cpan-ff9377addf4 )