January 06, 2013 Re: Linking with FFmpeg | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | Johannes Pfau:
> also says C int is the same as D int.
How is this possible?
Bye,
bearophile
|
January 06, 2013 Re: Linking with FFmpeg | ||||
---|---|---|---|---|
| ||||
Posted in reply to MrOrdinaire | 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 Re: Linking with FFmpeg | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 Re: Linking with FFmpeg | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | 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 Re: Linking with FFmpeg | ||||
---|---|---|---|---|
| ||||
Posted in reply to MrOrdinaire | 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.
|
Copyright © 1999-2021 by the D Language Foundation