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.hitself, but is actually withstrsafe.hinstead, whichdshow.hincludes by default.strsafe.hcontains the following code 1:1 There are similar
#pragmaand#definestatements for many other deprecated "unsafe" C functions.If both
STRSAFE_NO_DEPRECATEandDEPRECATE_SUPPORTEDare not defined (which is the case in this situation), the use of#define sprintfcauses all subsequent references to any kind ofsprintfsymbol to be seen assprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;during compiling.That is why you are getting the compiler error. When
vcl.his included beforestrsafe.h,dstring.hgets included first, so the compiler sees the correct declaration for theAnsiString::sprintf()method, and thenstrsafe.hgets included (presumably byUnit1.h) before the compiler sees yourTimer1Timer()code, so your calls toAnsiString().sprint("%i",i)are actually trying to callAnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i), which fail.When you swap the
vcl.handdshow.hincludes, the#define sprintfstatement instrsafe.hgets processed beforedstring.his included, so the compiler sees the following declaration for theAnsiString::sprintf()method indstring.hand fails:To prevent this behavior, you could use an
#undef sprintfstatement after#include <dshow.h>, like JeffRSon suggested. However the correct solution is to defineSTRSAFE_NO_DEPRECATEbefore#include <strsafe.h>. You can do that by either:adding
#define STRSAFE_NO_DEPRECATEto your code before the#include <dshow.h>statementadding
STRSAFE_NO_DEPRECATEto the Conditionals list in your Project Options.This solution is described on MSDN:
About Strsafe.h
Another supported solution is to define
NO_DSHOW_STRSAFEbefore#include <dshow.h>so that it will not includestrsafe.hanymore, thanks to this code indshow.h: