Including DShow.h breaks VCL AnsiString::sprintf() on BDS2006 - c++

I finally got some time to upgrade my video capture class. I wanted to compare VFW (what I have used until now) and DirectShow. As expected, DirectShow is faster, but when I added info texts, suddenly AnsiString::sprint() is no longer a member of AnsiString.
After some struggle, I found a workaround as AnsiString::printf() still works, but I am curious how to fix this. Maybe some define from dshow.h and dstring.h are conflicting?
I cut down all the unnecessary code to show this problem:
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#include <dshow.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
static int i=0;
Caption=AnsiString().sprintf("%i",i); // this does not work
AnsiString s; s.printf("%i",i); Caption=s; // this does work
i++;
}
//---------------------------------------------------------------------------
It is just a simple VCL Form app with a single TTimer on it. The TTimer is incrementing the counter i and outputting it in the Form's Caption. The DirectX libs are not even linked, just headers included!
The Linker outputs error:
[C++ Error] Unit1.cpp(20): E2316 'sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA' is not a member of 'AnsiString'
If I swap the vcl.h and dshow.hincludes, the compiler stops indstring.h` on this line:
AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
With this error message:
[C++ Error] dstring.h(59): E2040 Declaration terminated incorrectly
So, there is clearly some conflict (the AnsiString keyword is the problem). Putting dshow.h into a namespace does not help, either.
Does anyone have any clues?
Q1. How to fix this?
Q2. What/where exactly is causing this?
The only solution that I can think of, and should work (but I want to avoid it if I can), is to create an OBJ (or DLL) with the DirectShow stuff, and then link that into a standard VCL project without including dshow.h in it, and of course the exports must be without any funny stuff, too.

The problem is not with dshow.h itself, but is actually with strsafe.h instead, which dshow.h includes by default.
strsafe.h contains the following code 1:
#ifndef STRSAFE_NO_DEPRECATE
// Deprecate all of the unsafe functions to generate compiletime errors. If you do not want
// this then you can #define STRSAFE_NO_DEPRECATE before including this file
#ifdef DEPRECATE_SUPPORTED
...
#pragma deprecated(sprintf)
...
#else // DEPRECATE_SUPPORTED
...
#undef sprintf
#define sprintf sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;
...
#endif // DEPRECATE_SUPPORTED
#endif // !STRSAFE_NO_DEPRECATE
1 There are similar #pragma and #define statements for many other deprecated "unsafe" C functions.
If both STRSAFE_NO_DEPRECATE and DEPRECATE_SUPPORTED are not defined (which is the case in this situation), the use of #define sprintf causes all subsequent references to any kind of sprintf symbol to be seen as sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA; during compiling.
That is why you are getting the compiler error. When vcl.h is included before strsafe.h, dstring.h gets included first, so the compiler sees the correct declaration for the AnsiString::sprintf() method, and then strsafe.h gets included (presumably by Unit1.h) before the compiler sees your Timer1Timer() code, so your calls to AnsiString().sprint("%i",i) are actually trying to call AnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i), which fail.
When you swap the vcl.h and dshow.h includes, the #define sprintf statement in strsafe.h gets processed before dstring.h is included, so the compiler sees the following declaration for the AnsiString::sprintf() method in dstring.h and fails:
AnsiString& __cdecl sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;(const char* format, ...); // Returns *this
To prevent this behavior, you could use an #undef sprintf statement after #include <dshow.h>, like JeffRSon suggested. However the correct solution is to define STRSAFE_NO_DEPRECATE before #include <strsafe.h>. You can do that by either:
adding #define STRSAFE_NO_DEPRECATE to your code before the #include <dshow.h> statement
adding STRSAFE_NO_DEPRECATE to the Conditionals list in your Project Options.
This solution is described on MSDN:
About Strsafe.h
When you include Strsafe.h in your file, the older functions replaced by the Strsafe.h functions will be deprecated. Attempts to use these older functions will result in a compiler error telling you to use the newer functions. If you want to override this behavior, include the following statement before including Strsafe.h.
#define STRSAFE_NO_DEPRECATE
To allow only character count functions, include the following statement before including Strsafe.h.
#define STRSAFE_NO_CB_FUNCTIONS
To allow only byte count functions, include the following statement before including Strsafe.h.
#define STRSAFE_NO_CCH_FUNCTIONS
Another supported solution is to define NO_DSHOW_STRSAFE before #include <dshow.h> so that it will not include strsafe.h anymore, thanks to this code in dshow.h:
#ifndef NO_DSHOW_STRSAFE
#define NO_SHLWAPI_STRFCNS
#include <strsafe.h>
#endif

I don't have this very version of dshow.h and dstring.h, so I cannot check it myself, but from the error messages you cite it seems that somewhere in dshow.h or its dependencies they declare an "sprintf" macro. You may look if you can find it.
In order to prevent that behaviour you need to delete this macro. Use
#undef sprintf
after the line that includes dshow.h.

Related

Macro for including headers [duplicate]

Is there a way to define a macro that contains a #include
directive in its body?
If I just put
the "#include", it gives the error
C2162: "expected macro formal parameter"
since here I am not using # to concatenate strings.
If I use "\# include", then I receive the following two errors:
error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion
Any help?
So like the others say, no, you can't have #include statements inside a macro, since the preprocessor only does one pass. However, you can make the preprocessor do basically the same thing with a gnarly trick I found myself using recently.
Realise that preprocessor directives won't do anything inside a macro, however they WILL do something in a file. So, you can stick a block of code you want to mutate into a file, thinking of it like a macro definition (with pieces that can be altered by other macros), and then #include this pseudo-macro file in various places (make sure it has no include guards!). It doesn't behave exactly like a macro would, but it can achieve some pretty macro-like results, since #include basically just dumps the contents of one file into another.
For example, consider including lots of similarly named headers that come in groups. It is tedious to write them all out, or perhaps even they are auto-generated. You can partially automate their inclusion by doing something like this:
Helper macros header:
/* tools.hpp */
#ifndef __TOOLS_HPP__
#def __TOOLS_HPP__
// Macro for adding quotes
#define STRINGIFY(X) STRINGIFY2(X)
#define STRINGIFY2(X) #X
// Macros for concatenating tokens
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_2 CAT
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z))
// etc...
#endif
Pseudo-macro file
/* pseudomacro.hpp */
#include "tools.hpp"
// NO INCLUDE GUARD ON PURPOSE
// Note especially FOO, which we can #define before #include-ing this file,
// in order to alter which files it will in turn #include.
// FOO fulfils the role of "parameter" in this pseudo-macro.
#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY( CAT_3(HEAD,FOO,TAIL) )
#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp
#include INCLUDE_FILE(head2,tail2.hpp)
#include INCLUDE_FILE(head3,tail3.hpp)
#include INCLUDE_FILE(head4,tail4.hpp)
// etc..
#undef INCLUDE_FILE
Source file
/* mainfile.cpp */
// Here we automate the including of groups of similarly named files
#define FOO _groupA_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupA_tail1.hpp"
// #include "head2_groupA_tail2.hpp"
// #include "head3_groupA_tail3.hpp"
// #include "head4_groupA_tail4.hpp"
#undef FOO
#define FOO _groupB_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupB_tail1.hpp"
// #include "head2_groupB_tail2.hpp"
// #include "head3_groupB_tail3.hpp"
// #include "head4_groupB_tail4.hpp"
#undef FOO
#define FOO _groupC_
#include "pseudomacro.hpp"
#undef FOO
// etc.
These includes could even be in the middle of codes blocks you want to repeat (with FOO altered), as the answer by Bing Jian requests: macro definition containing #include directive
I haven't used this trick extensively, but it gets my job done. It can obviously be extended to have as many "parameters" as needed, and you can run whatever preprocessor commands you like in there, plus generate actual code. You just can't use the stuff it creates as the input into another macro, like you can with normal macros, since you can't stick the include inside a macro. But it can go inside another pseudo-macro :).
Others might have some comments on other limitations, and what could go wrong :).
I will not argue the merits for it, but freetype (www.freetype.org) does the following:
#include FT_FREETYPE_H
where they define FT_FREETYPE_H elsewhere
C and C++ languages explicitly prohibit forming preprocessor directives as the result of macro expansion. This means that you can't include a preprocessor directive into a macro replacement list. And if you try to trick the preprocessor by "building" a new preprocessor directive through concatenation (and tricks like that), the behavior is undefined.
I believe the C/C++ preprocessor only does a single pass over the code, so I don't think that would work. You might be able to get a "#include" to be placed in the code by the macro, but the compiler would choke on it, since it doesn't know what to do with that. For what you're trying to do to work the preprocessor would have to do a second pass over the file in order to pick up the #include.
I also wanted to do this, and here's the reason:
Some header files (notably mpi.h in OpenMPI) work differently if you are compiling in C or C++. I'm linking to a C MPI code from my C++ program. To include the header, I do the usual:
extern "C" {
#include "blah.h"
}
But this doesn't work because __cplusplus is still defined even in C linkage. That means mpi.h, which is included by blah.h, starts defining templates and the compiler dies saying you can't use templates with C linkage.
Hence, what I have to do in blah.h is to replace
#include <mpi.h>
with
#ifdef __cplusplus
#undef __cplusplus
#include <mpi.h>
#define __cplusplus
#else
#include <mpi.h>
#endif
Remarkably it's not just mpi.h that does this pathological thing. Hence, I want to define a macro INCLUDE_AS_C which does the above for the specified file. But I guess that doesn't work.
If anyone can figure out another way of accomplishing this, please let me know.
I think you are all right in that this task seems impossible as I also got from
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#
No, preprocessor directives in C++
(and C) are not reflective.
Pawel Dziepak
Anyway, the reason behind this attempt is that I am trying to make the following
repeatedly used code snippet as a macro:
void foo(AbstractClass object)
{
switch (object.data_type())
{
case AbstractClass::TYPE_UCHAR :
{
typedef unsigned char PixelType;
#include "snippets/foo.cpp"
}
break;
case AbstractClass::TYPE_UINT:
{
typedef unsigned int PixelType;
#include "snippets/foo.cpp"
}
break;
default:
break;
}
}
For another task, I need to have a similar function
void bar(AbstractClass object)
where I will place
#include "snippets/bar.cpp"
and of course it is in "snippets/foo.cpp" and "snippets/bar.cpp" that the task-specific code is written.
I have no idea what you are actually trying to do but it looks like what you might want is a templated function.
That way the PixelType is just a template parameter to the block of code.
Why would the macro need to have an #include? if you're #include'ing whatever file the macro is in, you could just put the #include above the macro with all the rest of the #include statements, and everything should be nice and dandy.
I see no reason to have the macro include anything that couldn't just be included in the file.
Contagious is right -- if you're doing:
myFile.c:
#include "standardAppDefs.h"
#myStandardIncludeMacro
standardAppDefs.h:
#define myStandardIncludeMacro #include <foo.h>
Why not just say:
myFile.c:
#include "standardAppDefs.h"
standardAppDefs.h:
#include <foo.h>
And forget the macros?

C++ How to protect oneself from stdio.h macros

I spent a long time trying to figure out why the following wouldn't compile:
enum IPC_RC {OK, EOF, ERROR, NEW };
The error message said only something to the effect that it wasn't expecting to see an open parenthesis. It wasn't until I tried compiling it on a more modern compiler that I learned:
/usr/include/stdio.h:201:13: note: expanded from macro 'EOF'
#define EOF (-1)
So I've finally been burned by a macro! :)
My code doesn't #include <stdio.h> (I don't include anything with a .h suffix), but clearly something I included resulted in the inclusion of <stdio.h>. Is there any way (namespaces?) to protect myself, without tracing down exactly where it was included?
Namespaces will not be a solution because macros ignore them.
So you have two options:
get rid of those macros yourself:
#ifdef EOF
#undef EOF
#endif
use a prefix with your enum values:
enum IPC_RC
{
IPC_OK,
IPC_EOF,
IPC_ERROR,
IPC_NEW
};
I don't know a satisfactory solution to the problem you describe, but I just wanted to share one way to handle the situation. Every now and then you (have to) use some particularly obnoxious header which redefins a good part of the English language. The X11 headers of Python.h come to mind. What I ended up doing - and it worked out very well - is that (usually after I notice the breakage) I wrap the 3rd party header in my own header and deal with the uglyness there.
For instance, in projects which make use of the Ruby interpreter, I usually don't include ruby.h directory but rather include an ourruby.h file which looks something like this:
#ifndef RUBY_OURRUBY_H
#define RUBY_OURRUBY_H
// In Ruby 1.9.1, win32.h includes window.h and then redefines some macros
// which causes warnings. We don't care about those (we cannot fix them).
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4005)
#endif
#include <ruby.h>
#ifdef _MSC_VER
# pragma warning(pop)
#endif
// In Ruby 1.8.7.330, win32.h defines various macros which break other code
#ifdef read
# undef read
#endif
#ifdef close
# undef close
#endif
#ifdef unlink
# undef unlink
#endif
// ...
#endif // !defined(RUBY_OURRUBY_H)
That way, I don't have to take care of remembering the fact that some headers are not exactly namespace clean.

How are circular #includes resolved?

In c lets say we have 2 files
1.h
#include<2.h>
blah blah
and we have
2.h
#include<1.h>
code
How is this resolved??
Typically you protect your include file with an ifndef/define that corresponds to the file name. This doesn't prevent the file from being included again, but it does prevent the contents (inside the ifndef) from being used and triggering the recursive includes again.
#ifndef HEADER_1_h
#define HEADER_1_h
#include "2.h"
/// rest of 1.h
#endif
#ifndef HEADER_2_h
#define HEADER_2_h
#include "1.h"
// rest of 2.h
#endif
Okay, for the sake of completeness I'll begin by quoting tvanfosson's answer:
You should use include guards:
// header1.hpp
#ifndef MYPROJECT_HEADER1_HPP_INCLUDED
#define MYPROJECT_HEADER1_HPP_INCLUDED
/// Put your stuff here
#endif // MYPROJECT_HEADER1_HPP_INCLUDED
However include guards are not meant to solve circular dependencies issues, they are meant to prevent multiple inclusions, which is quite different.
base.h
/ \
header1.h header2.h
\ /
class.cpp
In this case (quite common), you only want base.h to be included once, and that's what include guards give you.
So this will effectively prevents the double inclusion... but you won't be able to compile!!
The problem can be illustrated by trying to reason as the compiler does:
Include "header1.hpp" > this defines the include guard
Include "header2.hpp
Try to include "header1.hpp" but doesn't because the include guard is already defined
Cannot correctly parse "header2.hpp" because the types coming from "header1.hpp" have not been defined yet (since it was skipped)
Back to "header1.hpp", and the types from "header2.hpp" are still missing since they could not be compiled, and thus it fails here too
In the end, you'll left with a big pile of error messages, but at least the compiler does not crash.
The solution is to somehow remove the need for this circular dependency.
Use forward declarations if possible
Split "header1.h" into 2 parts: the part independent from header2 and the other, you should only need to include the former in header2
And THIS will solve the circular dependency (manually) there is no magic going on in the compiler that will do it for you.
Since you posted your question under the c++ tag as well as c, then I am assuming you are using c++. In c++, you can also use the #pragma once compiler directive:
1.h:
#pragma once
#include "2.h"
/// rest of 1.h
2.h:
#pragma once
#include "1.h"
/// rest of 2.h
The result is the same. But there are some notes:
pragma once will usually compile a little faster since it is a higher level mechanism and doesn't happen at preprocessing like include guards
Some compilers have known bugs "dealing" with #pragma once. Though most if not all modern compilers will handle it correctly. For a detailed list see Wikipedia
Edit: I think the directive is also supported in c compilers but have never tried it, and besides, in most c programs I've seen, include guards are the standard (maybe due to compiler limitations handling the pragma once directive?)
Circular inclusions must be eliminated, not "resolved" with include guards (as the accepted answer suggests). Consider this:
1.h:
#ifndef HEADER_1_h
#define HEADER_1_h
#include "2.h"
#define A 1
#define B 2
#endif // HEADER_1_h
2.h:
#ifndef HEADER_2_h
#define HEADER_2_h
#include "1.h"
#if (A == B)
#error Impossible
#endif
#endif // HEADER_2_h
main.c:
#include "1.h"
This will throw the "Impossible" error at compile time, because "2.h" fails to include "1.h" due to include guards, and both A and B become 0. In practice, this leads to hard to track errors which appear and disappear depending on the order in which header files are included.
The right solution here would be to move A and B to "common.h" which then could be included in both "1.h" and "2.h".

How do I avoid name collision with macros defined in Windows header files?

I have some C++ code that includes a method called CreateDirectory(). Previously the code only used STL and Boost, but I recently had to include <windows.h> so I could look-up CSIDL_LOCAL_APPDATA.
Now, this code:
filesystem.CreateDirectory(p->Pathname()); // Actually create it...
No longer compiles:
error C2039: 'CreateDirectoryA' : is not a member of ...
Which corresponds to this macro in winbase.h:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
The pre-processor is redefining my method call. Is there any possible way to avoid this naming collision? Or do I have to rename my CreateDirectory() method?
You will be better off if you just rename your CreateDirectory method. If you need to use windows APIs, fighting with Windows.h is a losing battle.
Incidently, if you were consistent in including windows.h, this will still be compiling. (although you might have problems in other places).
You could create a module whose sole purpose is to #include <windows.h> and look up CSIDL_LOCAL_APPDATA wrapped in a function.
int get_CSIDL_LOCAL_APPDATA(void)
{
return CSIDL_LOCAL_APPDATA;
}
btw, Well done for working out what happened!
#undef CreateDirectory
As a developer working on a cross platform codebase, this is a problem. The only way to deal with it is to
ensure that windows.h is - on Windows builds at least - universally included. Then the CreateDirectory macro is defined in every one of your compilation units and is universally substituted with CreateDirectoryW. Precompiled headers are ideal for this
OR, if that is an unpleasant proposition, (and it is for me)
isolate windows.h usage into windows specific utility files. Create files that export the basic required functionality. The header files must use data types that are compatible with, but do NOT depend on the inclusion of windows.h. The cpp implementation file must (obviously) use windows.h.
If your utlility functions need to include project header files with conflicting symbols then the following pattern is a necessity:
#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...
You will need to then explicitly call the non macro version of any windows api functions you have #undef'd - CreateDirectoryA or W etc.
push macro, undef it and pop the macro again:
#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
// ...
}
#pragma pop_macro("CreateDirectory")
You can take a back up of CreateDirectory, then undefine it, and then define it again when you finish your job with you custom one.
#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif
// ...
// Define and use your own CreateDirectory() here.
// ...
#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
Note that name conflict usually comes from a certain header file being included. Until then stuff like CreateDirectory and GetMessage isn't pulled into visibility and code compiles without a problem.
You can isolate such an inclusion into a wrapper header file and "#undef whatever" at its end. Then, whatever name collision you have will be gone. Unless, of course, you need to use those macros in your own code (yeah, so very likely...)
#pragma push_macro("CreateDirectory")
If nothing works, instead of renaming you could use your own namespace for your functions.

macro definition containing #include directive

Is there a way to define a macro that contains a #include
directive in its body?
If I just put
the "#include", it gives the error
C2162: "expected macro formal parameter"
since here I am not using # to concatenate strings.
If I use "\# include", then I receive the following two errors:
error C2017: illegal escape sequence
error C2121: '#' : invalid character : possibly the result of a macro expansion
Any help?
So like the others say, no, you can't have #include statements inside a macro, since the preprocessor only does one pass. However, you can make the preprocessor do basically the same thing with a gnarly trick I found myself using recently.
Realise that preprocessor directives won't do anything inside a macro, however they WILL do something in a file. So, you can stick a block of code you want to mutate into a file, thinking of it like a macro definition (with pieces that can be altered by other macros), and then #include this pseudo-macro file in various places (make sure it has no include guards!). It doesn't behave exactly like a macro would, but it can achieve some pretty macro-like results, since #include basically just dumps the contents of one file into another.
For example, consider including lots of similarly named headers that come in groups. It is tedious to write them all out, or perhaps even they are auto-generated. You can partially automate their inclusion by doing something like this:
Helper macros header:
/* tools.hpp */
#ifndef __TOOLS_HPP__
#def __TOOLS_HPP__
// Macro for adding quotes
#define STRINGIFY(X) STRINGIFY2(X)
#define STRINGIFY2(X) #X
// Macros for concatenating tokens
#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y
#define CAT_2 CAT
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z))
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z))
// etc...
#endif
Pseudo-macro file
/* pseudomacro.hpp */
#include "tools.hpp"
// NO INCLUDE GUARD ON PURPOSE
// Note especially FOO, which we can #define before #include-ing this file,
// in order to alter which files it will in turn #include.
// FOO fulfils the role of "parameter" in this pseudo-macro.
#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY( CAT_3(HEAD,FOO,TAIL) )
#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp
#include INCLUDE_FILE(head2,tail2.hpp)
#include INCLUDE_FILE(head3,tail3.hpp)
#include INCLUDE_FILE(head4,tail4.hpp)
// etc..
#undef INCLUDE_FILE
Source file
/* mainfile.cpp */
// Here we automate the including of groups of similarly named files
#define FOO _groupA_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupA_tail1.hpp"
// #include "head2_groupA_tail2.hpp"
// #include "head3_groupA_tail3.hpp"
// #include "head4_groupA_tail4.hpp"
#undef FOO
#define FOO _groupB_
#include "pseudomacro.hpp"
// "expands" to:
// #include "head1_groupB_tail1.hpp"
// #include "head2_groupB_tail2.hpp"
// #include "head3_groupB_tail3.hpp"
// #include "head4_groupB_tail4.hpp"
#undef FOO
#define FOO _groupC_
#include "pseudomacro.hpp"
#undef FOO
// etc.
These includes could even be in the middle of codes blocks you want to repeat (with FOO altered), as the answer by Bing Jian requests: macro definition containing #include directive
I haven't used this trick extensively, but it gets my job done. It can obviously be extended to have as many "parameters" as needed, and you can run whatever preprocessor commands you like in there, plus generate actual code. You just can't use the stuff it creates as the input into another macro, like you can with normal macros, since you can't stick the include inside a macro. But it can go inside another pseudo-macro :).
Others might have some comments on other limitations, and what could go wrong :).
I will not argue the merits for it, but freetype (www.freetype.org) does the following:
#include FT_FREETYPE_H
where they define FT_FREETYPE_H elsewhere
C and C++ languages explicitly prohibit forming preprocessor directives as the result of macro expansion. This means that you can't include a preprocessor directive into a macro replacement list. And if you try to trick the preprocessor by "building" a new preprocessor directive through concatenation (and tricks like that), the behavior is undefined.
I believe the C/C++ preprocessor only does a single pass over the code, so I don't think that would work. You might be able to get a "#include" to be placed in the code by the macro, but the compiler would choke on it, since it doesn't know what to do with that. For what you're trying to do to work the preprocessor would have to do a second pass over the file in order to pick up the #include.
I also wanted to do this, and here's the reason:
Some header files (notably mpi.h in OpenMPI) work differently if you are compiling in C or C++. I'm linking to a C MPI code from my C++ program. To include the header, I do the usual:
extern "C" {
#include "blah.h"
}
But this doesn't work because __cplusplus is still defined even in C linkage. That means mpi.h, which is included by blah.h, starts defining templates and the compiler dies saying you can't use templates with C linkage.
Hence, what I have to do in blah.h is to replace
#include <mpi.h>
with
#ifdef __cplusplus
#undef __cplusplus
#include <mpi.h>
#define __cplusplus
#else
#include <mpi.h>
#endif
Remarkably it's not just mpi.h that does this pathological thing. Hence, I want to define a macro INCLUDE_AS_C which does the above for the specified file. But I guess that doesn't work.
If anyone can figure out another way of accomplishing this, please let me know.
I think you are all right in that this task seems impossible as I also got from
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#
No, preprocessor directives in C++
(and C) are not reflective.
Pawel Dziepak
Anyway, the reason behind this attempt is that I am trying to make the following
repeatedly used code snippet as a macro:
void foo(AbstractClass object)
{
switch (object.data_type())
{
case AbstractClass::TYPE_UCHAR :
{
typedef unsigned char PixelType;
#include "snippets/foo.cpp"
}
break;
case AbstractClass::TYPE_UINT:
{
typedef unsigned int PixelType;
#include "snippets/foo.cpp"
}
break;
default:
break;
}
}
For another task, I need to have a similar function
void bar(AbstractClass object)
where I will place
#include "snippets/bar.cpp"
and of course it is in "snippets/foo.cpp" and "snippets/bar.cpp" that the task-specific code is written.
I have no idea what you are actually trying to do but it looks like what you might want is a templated function.
That way the PixelType is just a template parameter to the block of code.
Why would the macro need to have an #include? if you're #include'ing whatever file the macro is in, you could just put the #include above the macro with all the rest of the #include statements, and everything should be nice and dandy.
I see no reason to have the macro include anything that couldn't just be included in the file.
Contagious is right -- if you're doing:
myFile.c:
#include "standardAppDefs.h"
#myStandardIncludeMacro
standardAppDefs.h:
#define myStandardIncludeMacro #include <foo.h>
Why not just say:
myFile.c:
#include "standardAppDefs.h"
standardAppDefs.h:
#include <foo.h>
And forget the macros?