I am trying to print ffmpeg
version in a C
program. I see that in the /libavutil/version.h
there is AV_VERSION
which should tell the version number in the format x.x.x
.
As a test I used some random numbers as function parameters like this: std::string version = AV_VERSION(3,4,2);
. The same error I get if I use LIBAVUTIL_VERSION_MAJOR
, LIBAVUTIL_VERSION_MINOR
and LIBAVUTIL_VERSION_MICRO
from the file. That was actually my first try to print the version number.
The error I get is invalid suffix '.2' on floating constant
or invalid suffix '.101' on floating constant
if I try to print std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;
I do understand that the preprocessor is thinking that the token is a float
, hence the error. How do you actually use this type of macro funtion?
That macro is in the file I mentioned above, so it must be a way to call that macro function without giving an error, thinking that is a mature library, and I guess other libraries use something similar for printing version number.
Here is how AV_VERSION
is defined in the header file and how I call it:
#define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
#define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c
#define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
#define AV_VERSION_MAJOR(a) ((a) >> 16)
#define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8)
#define AV_VERSION_MICRO(a) ((a) & 0xFF)
#define LIBAVUTIL_VERSION_MAJOR 57
#define LIBAVUTIL_VERSION_MINOR 9
#define LIBAVUTIL_VERSION_MICRO 101
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
LIBAVUTIL_VERSION_MICRO)
#define LIBAVUTIL_VERSION AV_VERSION(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
LIBAVUTIL_VERSION_MICRO)
int main()
{
std::string version = AV_VERSION(3,4,2);
std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;
return 0;
}
I coud've skip this error but as I'm trying to learn C I am pretty sure that I will find more of this type of macros so no point to avoid learning them now as I'm facing them.
Thanks in advance!
CodePudding user response:
You need to use a stringize expansion. Because of how the preprocessor works, this involves two macros:
#define STR(x) #x
#define XSTR(x) STR(x)
The macro STR
will take whatever parameter you give it and make that a string literal.
The macro XSTR
will first expand its parameter x
and the result will be the parameter to STR
.
To illustrate:
STR(LIBAVUTIL_VERSION)
will give"LIBAVUTIL_VERSION"
XSTR(LIBAVUTIL_VERSION)
will give"57.9.101"
Demo according to your code:
int main()
{
std::string version1 = XSTR(LIBAVUTIL_VERSION);
std::string version2 = XSTR(AV_VERSION(3,4,2));
std::cout << version1 << "\n";
std::cout << version2 << "\n";
return 0;
}
Output:
57.9.101
3.4.2