View mode: basic / threaded / horizontal-split · Log in · Help
October 22, 2012
Correct way to map C #define to version
Hi,

My first post here as a new D user. I am trying to interface with 
FFmpeg with D and need some guidance on how to replicate the 
version semantics in a C header. I'd like to open source the D 
modules files so I want to get this right.

FFMpeg defines a bunch of constants that are then used in the 
headers to include/exclude fields from structs.

e.g.

struct AVFilterBufferRefAudioProps {
    uint64_t channel_layout;    ///< channel layout of audio 
buffer
    int nb_samples;             ///< number of audio samples per 
channel
    int sample_rate;            ///< audio buffer sample rate
#if FF_API_PACKING
    int planar;                 ///< audio buffer - planar or 
packed
#endif
} AVFilterBufferRefAudioProps;

where FF_API_PACKING is defines as:

#define LIBAVFILTER_VERSION_MAJOR  2
#define LIBAVFILTER_VERSION_MINOR 77
#define LIBAVFILTER_VERSION_MICRO 100
.
.
.
#ifndef FF_API_PACKING
#define FF_API_PACKING                  
(LIBAVFILTER_VERSION_MAJOR < 3)
#endif

I tried to do the following:

version (V54_23_100) {
  version = FF_API_PACKING;
}

and then specify the version at the top of my D interface files:

version = V54_23_100

and define the struct as

struct AVFilterBufferRefAudioProps {
    uint64_t channel_layout;    ///< channel layout of audio 
buffer
    int nb_samples;             ///< number of audio samples per 
channel
    int sample_rate;            ///< audio buffer sample rate
version(FF_API_PACKING) {
    int planar;                  ///< audio buffer - planar or 
packed
}
}

but this resulted in the wrong size of struct when the C 
functions were called - the struct did not container the planer 
field.

Am I using version correctly? How is this done usually?

Thanks

Sumit
October 22, 2012
Re: Correct way to map C #define to version
Sumit Raja:

> Am I using version correctly? How is this done usually?

I think "version" is usually meant to be given as compiler 
switch. Maybe a simple enum + static if is enough in your case.

And keep in mind that C int and D int are different on 64 bit 
systems, the D int is always 32 bit. In Phobos there are ints of 
the size of C.

Bye,
bearophile
October 22, 2012
Re: Correct way to map C #define to version
On Mon, 22 Oct 2012 12:39:48 +0100, bearophile <bearophileHUGS@lycos.com>  
wrote:

> Sumit Raja:
>
>> Am I using version correctly? How is this done usually?
>
> I think "version" is usually meant to be given as compiler switch. Maybe  
> a simple enum + static if is enough in your case.

Good suggestion.  I was curious so I had a tinker and produced this  
example which might be useful to you.

import core.stdc.stdint;
import std.stdio;

enum LIBAVFILTER_VERSION_MAJOR = 2;  	\\ change this to 3 to see a  
difference in size below
enum LIBAVFILTER_VERSION_MINOR = 77;
enum LIBAVFILTER_VERSION_MICRO = 100;

enum FF_API_PACKING = (LIBAVFILTER_VERSION_MAJOR < 3);

struct AVFilterBufferRefAudioProps {
    uint64_t channel_layout;    ///< channel layout of audio buffer
    int nb_samples;             ///< number of audio samples per channel
    int sample_rate;            ///< audio buffer sample rate
static if(FF_API_PACKING) {
    int planar;                  ///< audio buffer - planar or packed
}
}

void main()
{
    writefln("size of AVFilterBufferRefAudioProps = %s",  
AVFilterBufferRefAudioProps.sizeof);
}

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
October 29, 2012
Re: Correct way to map C #define to version
On Monday, 22 October 2012 at 12:44:35 UTC, Regan Heath wrote:
> On Mon, 22 Oct 2012 12:39:48 +0100, bearophile 
> <bearophileHUGS@lycos.com> wrote:
>
>> Sumit Raja:
>>
>>> Am I using version correctly? How is this done usually?
>>
>> I think "version" is usually meant to be given as compiler 
>> switch. Maybe a simple enum + static if is enough in your case.
>
> Good suggestion.  I was curious so I had a tinker and produced 
> this example which might be useful to you.
>
> import core.stdc.stdint;
> import std.stdio;
>
> enum LIBAVFILTER_VERSION_MAJOR = 2;  	\\ change this to 3 to 
> see a difference in size below
> enum LIBAVFILTER_VERSION_MINOR = 77;
> enum LIBAVFILTER_VERSION_MICRO = 100;
>
> enum FF_API_PACKING = (LIBAVFILTER_VERSION_MAJOR < 3);
>
> struct AVFilterBufferRefAudioProps {
>     uint64_t channel_layout;    ///< channel layout of audio 
> buffer
>     int nb_samples;             ///< number of audio samples 
> per channel
>     int sample_rate;            ///< audio buffer sample rate
> static if(FF_API_PACKING) {
>     int planar;                  ///< audio buffer - planar or 
> packed
> }
> }
>
> void main()
> {
>     writefln("size of AVFilterBufferRefAudioProps = %s", 
> AVFilterBufferRefAudioProps.sizeof);
> }
>
> R

Thanks both this works great for structs. Anything similar I can 
do for enums?
October 29, 2012
Re: Correct way to map C #define to version
On Mon, 29 Oct 2012 11:31:33 -0000, Sumit Raja <sumitraja@gmail.com> wrote:
> Thanks both this works great for structs. Anything similar I can do for  
> enums?

Example?  (The C/C++ code you're trying to convert..)

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
October 29, 2012
Re: Correct way to map C #define to version
On Monday, 29 October 2012 at 12:31:56 UTC, Regan Heath wrote:
> On Mon, 29 Oct 2012 11:31:33 -0000, Sumit Raja 
> <sumitraja@gmail.com> wrote:
>> Thanks both this works great for structs. Anything similar I 
>> can do for enums?
>
> Example?  (The C/C++ code you're trying to convert..)

Yeah that might help... One example here (though it seems 
slightly inconsistent as the enum following the second if seems 
to be padded for the values inside the ifdef):

enum PixelFormat {
    PIX_FMT_NONE= -1,
.
.
.
#ifdef AV_PIX_FMT_ABI_GIT_MASTER
    PIX_FMT_RGBA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 
16G, 16B, 16A, the 2-byte value for each R/G/B/A component is 
stored as big-endian
    PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 
16G, 16B, 16A, the 2-byte value for each R/G/B/A component is 
stored as little-endian
    PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 
16G, 16R, 16A, the 2-byte value for each R/G/B/A component is 
stored as big-endian
    PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 
16G, 16R, 16A, the 2-byte value for each R/G/B/A component is 
stored as little-endian
#endif
    PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
.
.
.
    PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little endian

#ifndef AV_PIX_FMT_ABI_GIT_MASTER
    PIX_FMT_RGBA64BE=0x123,  ///< packed RGBA 16:16:16:16, 64bpp, 
16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component 
is stored as big-endian
    PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 
16G, 16B, 16A, the 2-byte value for each R/G/B/A component is 
stored as little-endian
    PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 
16G, 16R, 16A, the 2-byte value for each R/G/B/A component is 
stored as big-endian
    PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 
16G, 16R, 16A, the 2-byte value for each R/G/B/A component is 
stored as little-endian
#endif
    PIX_FMT_0RGB=0x123+4,      ///< packed RGB 8:8:8, 32bpp, 
0RGB0RGB...
.
.
.
};
October 29, 2012
Re: Correct way to map C #define to version
On Mon, 29 Oct 2012 13:47:46 -0000, Sumit Raja <sumitraja@gmail.com> wrote:
> On Monday, 29 October 2012 at 12:31:56 UTC, Regan Heath wrote:
>> On Mon, 29 Oct 2012 11:31:33 -0000, Sumit Raja <sumitraja@gmail.com>  
>> wrote:
>>> Thanks both this works great for structs. Anything similar I can do  
>>> for enums?
>>
>> Example?  (The C/C++ code you're trying to convert..)
>
> Yeah that might help... One example here (though it seems slightly  
> inconsistent as the enum following the second if seems to be padded for  
> the values inside the ifdef):
>
> enum PixelFormat {
>      PIX_FMT_NONE= -1,
> .
> .
> .
> #ifdef AV_PIX_FMT_ABI_GIT_MASTER
>      PIX_FMT_RGBA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,  
> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as  
> big-endian
>      PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,  
> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as  
> little-endian
>      PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,  
> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as  
> big-endian
>      PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,  
> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as  
> little-endian
> #endif
>      PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
> .
> .
> .
>      PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little endian
>
> #ifndef AV_PIX_FMT_ABI_GIT_MASTER
>      PIX_FMT_RGBA64BE=0x123,  ///< packed RGBA 16:16:16:16, 64bpp, 16R,  
> 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as  
> big-endian
>      PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,  
> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as  
> little-endian
>      PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,  
> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as  
> big-endian
>      PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,  
> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as  
> little-endian
> #endif
>      PIX_FMT_0RGB=0x123+4,      ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB...
> .
> .
> .
> };

Well, I can't see a way to do that in D without duplicating most of the  
enum.  :(

If no-one else can think of a way, I reckon we want an enhancement request  
to allow "version" or "static if" or perhaps "mixin" inside enums...

http://d.puremagic.com/issues/

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
October 29, 2012
Re: Correct way to map C #define to version
On 10/29/2012 03:14 PM, Regan Heath wrote:
> On Mon, 29 Oct 2012 13:47:46 -0000, Sumit Raja <sumitraja@gmail.com> wrote:
>> On Monday, 29 October 2012 at 12:31:56 UTC, Regan Heath wrote:
>>> On Mon, 29 Oct 2012 11:31:33 -0000, Sumit Raja <sumitraja@gmail.com>
>>> wrote:
>>>> Thanks both this works great for structs. Anything similar I can do
>>>> for enums?
>>>
>>> Example?  (The C/C++ code you're trying to convert..)
>>
>> Yeah that might help... One example here (though it seems slightly
>> inconsistent as the enum following the second if seems to be padded
>> for the values inside the ifdef):
>>
>> enum PixelFormat {
>>      PIX_FMT_NONE= -1,
>> .
>> .
>> .
>> #ifdef AV_PIX_FMT_ABI_GIT_MASTER
>>      PIX_FMT_RGBA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,
>> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as
>> big-endian
>>      PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,
>> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as
>> little-endian
>>      PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,
>> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as
>> big-endian
>>      PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,
>> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as
>> little-endian
>> #endif
>>      PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
>> .
>> .
>> .
>>      PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little endian
>>
>> #ifndef AV_PIX_FMT_ABI_GIT_MASTER
>>      PIX_FMT_RGBA64BE=0x123,  ///< packed RGBA 16:16:16:16, 64bpp,
>> 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is
>> stored as big-endian
>>      PIX_FMT_RGBA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G,
>> 16B, 16A, the 2-byte value for each R/G/B/A component is stored as
>> little-endian
>>      PIX_FMT_BGRA64BE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,
>> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as
>> big-endian
>>      PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G,
>> 16R, 16A, the 2-byte value for each R/G/B/A component is stored as
>> little-endian
>> #endif
>>      PIX_FMT_0RGB=0x123+4,      ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB...
>> .
>> .
>> .
>> };
>
> Well, I can't see a way to do that in D without duplicating most of the
> enum.  :(
>
> If no-one else can think of a way, I reckon we want an enhancement
> request to allow "version" or "static if" or perhaps "mixin" inside
> enums...
>
> http://d.puremagic.com/issues/
>
> R
>

You could mixin the entire enum, like this:
https://github.com/MikeWey/DMagick/blob/master/dmagick/c/distort.d#L239

-- 
Mike Wey
Top | Discussion index | About this forum | D home