digitalmars.D.learn - Linking with FFmpeg
- MrOrdinaire (21/21) Jan 06 2013 Hi,
- bearophile (12/21) Jan 06 2013 D ints are 32 bit long, while the length of C ints varies across
- MrOrdinaire (8/30) Jan 06 2013 Thank you for your reply.
- bearophile (12/17) Jan 06 2013 Right. It's a D coding style convention that has a practical
- Johannes Pfau (6/13) Jan 06 2013 Are you sure about c_int? I never heard of that before, I only know
- bearophile (4/5) Jan 06 2013 How is this possible?
- bearophile (4/7) Jan 06 2013 In D "ubyte" is probably enough, instead of "uint8_t".
- MrOrdinaire (5/12) Jan 06 2013 Thanks for noting that. I know that in std.stdint, uint8_t is an
- Johannes Pfau (12/23) Jan 06 2013 My C is pretty bad, is uint8_t *pointers[4] a static array with 4
- MrOrdinaire (5/31) Jan 06 2013 According to this (http://c-faq.com/decl/spiral.anderson.html), I
- H. S. Teoh (29/47) Jan 06 2013 The first parameter should be: uint8_t* pointers, and you need to call
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (77/80) Jan 06 2013 1) No array is passed to a function as-is in C. Even though there seem
- Johannes Pfau (22/27) Jan 06 2013 With C's arrays are pointers thing, that might be true. But the
- MrOrdinaire (5/41) Jan 06 2013 I agree with you.
- Johannes Pfau (4/10) Jan 07 2013 I wasn't sure if it's necessary. Imho it makes the code easier to read
Hi, I am working on D bindings for FFmpeg. I am trying to port the official examples of FFmpeg to D so that the bindings can be tested. 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); My best guess is the following. extern(C) int av_image_alloc(ref uint8_t[4] *pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_); However, calling this would give nonsense value for the array passed as linesizes. I don't know how to look at the variable passed as pointers yet. The whole source of the port is at https://gist.github.com/4466289, there you can also find the link to the original source. Thanks, Minh
Jan 06 2013
MrOrdinaire: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); My best guess is the following. extern(C) int av_image_alloc(ref uint8_t[4] *pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_);D ints are 32 bit long, while the length of C ints varies across different architectures. So you can't use int in your D signature. sizediff_t is better, but I remember there is a more specific type for this purpose, something like cint_t, I don't remember. In D the pointer symbol "*" is better (more meaningful) written justified on the right. If you use a D ref, you can't put a null there. Others will give you a better answer. Bye, bearophile
Jan 06 2013
On Sunday, 6 January 2013 at 10:21:56 UTC, bearophile wrote:MrOrdinaire:Thank you for your reply. I cannot find "cint_t" nor "cint" in the d standard modules (mine are at /usr/include/d/). For the symbol "*", do you mean I should write something like this? uint8_t[4]* ptrs - MinhMy 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); My best guess is the following. extern(C) int av_image_alloc(ref uint8_t[4] *pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_);D ints are 32 bit long, while the length of C ints varies across different architectures. So you can't use int in your D signature. sizediff_t is better, but I remember there is a more specific type for this purpose, something like cint_t, I don't remember. In D the pointer symbol "*" is better (more meaningful) written justified on the right. If you use a D ref, you can't put a null there. Others will give you a better answer. Bye, bearophile
Jan 06 2013
MrOrdinaire:I cannot find "cint_t" nor "cint" in the d standard modules (mine are at /usr/include/d/).I don't remember the correct name.For the symbol "*", do you mean I should write something like this? uint8_t[4]* ptrsRight. It's a D coding style convention that has a practical base. In C this means a is a pointer and b is an integer, while in D it means both are pointers: int *a, b; In C this means a is an int and b is a pointer, while in D it's thankfully an error (Error: multiple declarations must have the same type, not int and int*): int a, *b; Bye, bearophile
Jan 06 2013
Am Sun, 06 Jan 2013 12:51:33 +0100 schrieb "bearophile" <bearophileHUGS lycos.com>:MrOrdinaire:Are you sure about c_int? I never heard of that before, I only know c_long and c_ulong (in core.stdc.config). http://dlang.org/interfaceToC.html also says C int is the same as D int.I cannot find "cint_t" nor "cint" in the d standard modules (mine are at /usr/include/d/).I don't remember the correct name.
Jan 06 2013
Johannes Pfau:also says C int is the same as D int.How is this possible? Bye, bearophile
Jan 06 2013
MrOrdinaire:For the symbol "*", do you mean I should write something like this? uint8_t[4]* ptrsIn D "ubyte" is probably enough, instead of "uint8_t". Bye, bearophile
Jan 06 2013
On Sunday, 6 January 2013 at 11:54:34 UTC, bearophile wrote:MrOrdinaire:Thanks for noting that. I know that in std.stdint, uint8_t is an alias for ubyte. However, I want to keep to the original source so that people can do a diff more easily. - MinhFor the symbol "*", do you mean I should write something like this? uint8_t[4]* ptrsIn D "ubyte" is probably enough, instead of "uint8_t". Bye, bearophile
Jan 06 2013
Am Sun, 06 Jan 2013 10:48:25 +0100 schrieb "MrOrdinaire" <mrordinaire gmail.com>:Hi, I am working on D bindings for FFmpeg. I am trying to port the official examples of FFmpeg to D so that the bindings can be tested. 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);My C is pretty bad, is uint8_t *pointers[4] a static array with 4 elements of uint8_t* or is it a pointer to a static array with 4 uint8_t elements? I guess it's the former, so in D it's (uint8_t*)[4] or better (ubyte*)[4]. In D static arrays are passed by value, in C by reference, so you have to do this: extern(C) int av_image_alloc(ref (ubyte*)[4] pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_); Some more information is here: http://dlang.org/interfaceToC.html
Jan 06 2013
On Sunday, 6 January 2013 at 12:46:05 UTC, Johannes Pfau wrote:Am Sun, 06 Jan 2013 10:48:25 +0100 schrieb "MrOrdinaire" <mrordinaire gmail.com>:According to this (http://c-faq.com/decl/spiral.anderson.html), I think pointers is an array of 4 pointers to uint8_t. So in D, you read declarations from right to left? - MinhHi, I am working on D bindings for FFmpeg. I am trying to port the official examples of FFmpeg to D so that the bindings can be tested. 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);My C is pretty bad, is uint8_t *pointers[4] a static array with 4 elements of uint8_t* or is it a pointer to a static array with 4 uint8_t elements? I guess it's the former, so in D it's (uint8_t*)[4] or better (ubyte*)[4]. In D static arrays are passed by value, in C by reference, so you have to do this: extern(C) int av_image_alloc(ref (ubyte*)[4] pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_); Some more information is here: http://dlang.org/interfaceToC.html
Jan 06 2013
On Sun, Jan 06, 2013 at 10:48:25AM +0100, MrOrdinaire wrote:Hi, I am working on D bindings for FFmpeg. I am trying to port the official examples of FFmpeg to D so that the bindings can be tested. 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); My best guess is the following. extern(C) int av_image_alloc(ref uint8_t[4] *pointers, ref int[4] linesizes, int w, int h, AVPixelFormat pix_fmt, int align_);The first parameter should be: uint8_t* pointers, and you need to call it like this: uint8_t[4] pointers; int[4] linesizes; auto ret = av_image_alloc(pointers.ptr, linesizes.ptr, ...); To make it D-friendly, you might want to consider using a wrapper function that takes ref uint8_t[4] and ref int[4] instead.However, calling this would give nonsense value for the array passed as linesizes. I don't know how to look at the variable passed as pointers yet.[...] Just write *ptr to dereference a pointer. You can also take advantage of D's auto-dereferencing: struct S { int val = 123; } S s; S* ptr = &s; writeln(s.val); // prints 123 writeln(ptr.val); // also prints 123 (ptr is automatically // dereferenced) Finally, please note that in D, the * in pointer types associate with the _type_ rather than the variable name (as in C/C++), so you should always write "int* x,y" instead of "int *x, *y". Similarly, an array of pointers is written as "int*[] arr", whereas writing "int[]* arr" is actually declaring a pointer to an array. (In D, pointers and arrays are not the same thing.) T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Miller
Jan 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); }
Jan 06 2013
Am Sun, 06 Jan 2013 09:43:11 -0800 schrieb Ali =C3=87ehreli <acehreli yahoo.com>:=20 Ali =20 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
Jan 06 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>: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.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
Jan 06 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.
Jan 07 2013