January 06, 2013
Johannes Pfau:

> also says C int is the same as D int.

How is this possible?

Bye,
bearophile
January 06, 2013
On 01/06/2013 01:48 AM, MrOrdinaire wrote:

> My question is how this function declaration is written in D.
> int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
> int w, int h, enum AVPixelFormat pix_fmt, int align);

1) No array is passed to a function as-is in C. Even though there seem to be arrays of 4 elements above, they are both passed as pointers to their first elements. (That 4 has no bearing at all.)

2) uint8_t *pointers[4] means an array of elements of type 'uint8_t*'.

3) int linesizes[4] means an array of ints.

4) uint8_t and friends are defined in the std.stdint module in Phobos.

5) enum should not be used in that signature in D.

6) align is a keyword and cannot be used.

This is the declaration of that function in D:

extern(C)
int av_image_alloc(uint8_t** pointers, int* linesizes,
                   int w, int h, AVPixelFormat pix_fmt, int alignment);


Here is a program that I used to test it:

import std.stdint;

extern(C)
{

enum AVPixelFormat
{
    one, two
}

int av_image_alloc(uint8_t** pointers, int* linesizes,
                   int w, int h, AVPixelFormat pix_fmt, int alignment);

}

void main()
{
    uint8_t ui0 = 7;
    uint8_t ui1 = 8;

    uint8_t*[] pointers = [ &ui0, &ui1 ];

    // Ditto
    int[] linesizes = [ 20, 30, 40 ];

    int result = av_image_alloc(pointers.ptr, linesizes.ptr,
                                44, 55, AVPixelFormat.two, 100);

    assert(result == 42);
}

I tested it with the following C file:

#include <stdint.h>
#include <assert.h>

enum AVPixelFormat
{
    AVPixelFormat_one, AVPixelFormat_two
};

int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
                   int w, int h, enum AVPixelFormat pix_fmt, int align)
{
    assert(*pointers[0] == 7);
    assert(*pointers[1] == 8);

    assert(linesizes[0] == 20);
    assert(linesizes[1] == 30);
    assert(linesizes[2] == 40);

    assert(w == 44);
    assert(h == 55);

    assert(pix_fmt == AVPixelFormat_two);
    assert(align == 100);

    return 42;
}

I compiled the C file like this:

$ gcc -c deneme.c

Then compiled the D program like this (note that the C .o was in a different directory):

$ dmd ../c/deneme.o deneme.d

And ran it like this:

$ ./deneme

All assertions passed. Yay! :)

Ali

P.S. To prove the point that that 4 in the signature has no meaning, I tested the C function also with the following C program:

int main()
{
    uint8_t ui0 = 7;
    uint8_t ui1 = 8;

    // Deliberately 10 (not 4) to prove a point
    uint8_t* pointers[10] = { &ui0, &ui1 };

    // Ditto
    int linesizes[10] = { 20, 30, 40 };

    av_image_alloc(pointers, linesizes, 44, 55, AVPixelFormat_two, 100);
}

January 06, 2013
Am Sun, 06 Jan 2013 09:43:11 -0800
schrieb Ali Çehreli <acehreli@yahoo.com>:

> 
> Ali
> 
> P.S. To prove the point that that 4 in the signature has no meaning, I tested the C function also with the following C program:

With C's arrays are pointers thing, that might be true. But the signature (and ffmpeg) documentation suggest that the av_image_alloc function will always write 4 ubyte* pointers to the pointers parameter. So you can't use an array smaller than 4 pointers. You can use more, as it doesn't matter for the ABI, but av_image_alloc will only use 4 pointers.

So I'd argue that ((ubyte*)[4])* is better as a type than ubyte** as it allows the D compiler to do more checks. And the Interfacing to C page recommends using ref for static arrays instead of a pointer, as that allows using the code as in C:

void av_image_alloc(ref (ubyte*)[4]);
(ubyte*)[4] ptr;
av_image_alloc(ptr);

void av_image_alloc((ubyte*)[4]*);
(ubyte*)[4] ptr;
av_image_alloc(&ptr); //need &

void av_image_alloc(ubyte**);
(ubyte*)[3] ptr;
ubyte* test; //overwritten, BUG!
av_image_alloc(&ptr); //need &, and accepts to small arrays, bug prone

January 07, 2013
On Sunday, 6 January 2013 at 18:39:32 UTC, Johannes Pfau wrote:
> Am Sun, 06 Jan 2013 09:43:11 -0800
> schrieb Ali Çehreli <acehreli@yahoo.com>:
>
>> 
>> Ali
>> 
>> P.S. To prove the point that that 4 in the signature has no meaning,
>> I tested the C function also with the following C program:
>
> With C's arrays are pointers thing, that might be true. But the
> signature (and ffmpeg) documentation suggest that the av_image_alloc
> function will always write 4 ubyte* pointers to the pointers parameter.
> So you can't use an array smaller than 4 pointers. You can use more, as
> it doesn't matter for the ABI, but av_image_alloc will only use 4
> pointers.
>
> So I'd argue that ((ubyte*)[4])* is better as a type than ubyte** as it
> allows the D compiler to do more checks. And the Interfacing to C page
> recommends using ref for static arrays instead of a pointer, as that
> allows using the code as in C:
>
> void av_image_alloc(ref (ubyte*)[4]);
> (ubyte*)[4] ptr;
> av_image_alloc(ptr);
>
> void av_image_alloc((ubyte*)[4]*);
> (ubyte*)[4] ptr;
> av_image_alloc(&ptr); //need &
>
> void av_image_alloc(ubyte**);
> (ubyte*)[3] ptr;
> ubyte* test; //overwritten, BUG!
> av_image_alloc(&ptr); //need &, and accepts to small arrays, bug prone

I agree with you.

One quick question, why do you need a pair of parentheses in these declarations, ref (ubyte*)[4] and (ubyte*)[4]? The compiler doesn't complain if I remove it.
January 07, 2013
Am Mon, 07 Jan 2013 03:31:51 +0100
schrieb "MrOrdinaire" <mrordinaire@gmail.com>:

> 
> I agree with you.
> 
> One quick question, why do you need a pair of parentheses in these declarations, ref (ubyte*)[4] and (ubyte*)[4]? The compiler doesn't complain if I remove it.

I wasn't sure if it's necessary. Imho it makes the code easier to read but that's probably just a personal preference.
1 2
Next ›   Last »