Translated C fails to compile: increased pointer alignment

I’m trying to use stb_image.h. These are the build errors:

/home/joe/dev/vulkan/.zig-cache/o/41dde7d2f223247e0e19c892e084d24d/cimport.zig:28581:69: error: @ptrCast increases pointer alignment
            var y_bytes: __m128i = _mm_loadl_epi64(@as([*c]__m128i, @ptrCast(@volatileCast(@constCast(y + @as(usize, @bitCast(@as(isize, @intCast(i)))))))));
                                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/joe/dev/vulkan/.zig-cache/o/41dde7d2f223247e0e19c892e084d24d/cimport.zig:28581:105: note: '[*c]const u8' has alignment '1'
            var y_bytes: __m128i = _mm_loadl_epi64(@as([*c]__m128i, @ptrCast(@volatileCast(@constCast(y + @as(usize, @bitCast(@as(isize, @intCast(i)))))))));
                                                                                                      ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/joe/dev/vulkan/.zig-cache/o/41dde7d2f223247e0e19c892e084d24d/cimport.zig:28581:69: note: '[*c]@Vector(2, c_longlong)' has alignment '16'
/home/joe/dev/vulkan/.zig-cache/o/41dde7d2f223247e0e19c892e084d24d/cimport.zig:28581:69: note: use @alignCast to assert pointer alignment
/home/joe/dev/vulkan/.zig-cache/o/41dde7d2f223247e0e19c892e084d24d/cimport.zig:31982:68: error: expected type '[4]u8', found 'u8'
            }).*[@as(c_uint, @intCast(@as(c_int, 2)))] = stbi__get8(s);
                                                         ~~~~~~~~~~^~~

The first error comes from the translation of this function:

static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step)
{
   int i = 0;

#ifdef STBI_SSE2
   // step == 3 is pretty ugly on the final interleave, and i'm not convinced
   // it's useful in practice (you wouldn't use it for textures, for example).
   // so just accelerate step == 4 case.
   if (step == 4) {
      // this is a fairly straightforward implementation and not super-optimized.
      __m128i signflip  = _mm_set1_epi8(-0x80);
      __m128i cr_const0 = _mm_set1_epi16(   (short) ( 1.40200f*4096.0f+0.5f));
      __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f));
      __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f));
      __m128i cb_const1 = _mm_set1_epi16(   (short) ( 1.77200f*4096.0f+0.5f));
      __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128);
      __m128i xw = _mm_set1_epi16(255); // alpha channel

      for (; i+7 < count; i += 8) {
         // load
         __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); // problem line
        // ...

Here’s the relevant C for the second error:

static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp)
{
   int i;
   for (i=0; i < num_entries; ++i) {
      pal[i][2] = stbi__get8(s); // problem line
      pal[i][1] = stbi__get8(s);
      pal[i][0] = stbi__get8(s);
      pal[i][3] = transp == i ? 0 : 255;
   }
}

stbi_inline static stbi_uc stbi__get8(stbi__context *s)
{
   if (s->img_buffer < s->img_buffer_end)
      return *s->img_buffer++;
   if (s->read_from_callbacks) {
      stbi__refill_buffer(s);
      return *s->img_buffer++;
   }
   return 0;
}

I don’t know whether this is a limitation of Zig’s translate-c, or if there’s something I can do about his. One thing that is weird is that the stbi_uc pal[256][4] argument to stbi__gif_parse_colortable get’s translated to a [*c][4]stbi_uc in zig.

1 Like

Zig’s translate C and @cImport features are intended to translate declarations in header files, not full implementations. To use header only libraries you should make a C file like

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

And link this with your project, and @cImport the stb_image.h without defining STB_IMAGE_IMPLEMENTATION.

That is the correct translation. Array parameters in C are very misleading since arrays are treated as addresses in C. See e.g. this Linus rant.

5 Likes

This worked, thanks!

I had the same problem with this library. I might give it a second try after this explanation.