我终于有时间升级我的视频捕获类(class)。我想比较 VFW (到目前为止我使用过的)和 DirectShow 。不出所料, DirectShow 更快,但是当我添加信息文本时,突然AnsiString::sprint()
不再是AnsiString
的成员。
经过一番努力后,我发现一种解决方法,因为AnsiString::printf()
仍然有效,但是我很好奇如何解决此问题。也许有人从dshow.h
和dstring.h
定义冲突?
我削减了所有不必要的代码以显示此问题:
//$$---- 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++;
}
//---------------------------------------------------------------------------
这只是一个简单的VCL Form应用程序,上面只有一个
TTimer
。 TTimer
将递增计数器i
并将其输出到表单的Caption
中。 DirectX 库甚至没有链接,仅包含 header !链接器输出错误:
[C++ Error] Unit1.cpp(20): E2316 'sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA' is not a member of 'AnsiString'
如果我在此行上交换
vcl.h
和dshow.h includes, the compiler stops in
dstring.h`:AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
出现此错误消息:
[C++ Error] dstring.h(59): E2040 Declaration terminated incorrectly
因此,显然存在一些冲突(
AnsiString
关键字是问题)。将dshow.h
放入namespace
也无济于事。有人有任何线索吗?
Q1。如何解决这个问题?
Q2。到底是什么/什么原因造成的?
我能想到的并且应该起作用的唯一解决方案(但如果可以的话,我想避免使用它)是使用 DirectShow 内容创建一个 OBJ (或 DLL ),然后将其链接到标准 VCL 项目,但其中不包含
dshow.h
,当然,导出内容也必须没有任何有趣的内容。 最佳答案
问题不在于dshow.h
本身,而是实际上与strsafe.h
相反,默认情况下dshow.h
包括该问题。strsafe.h
包含以下代码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对于许多其他不推荐使用的“不安全” C函数,也有类似的
#pragma
和#define
语句。如果没有同时定义
STRSAFE_NO_DEPRECATE
和DEPRECATE_SUPPORTED
(在这种情况下就是这种情况),则#define sprintf
的使用会导致对任何类型的sprintf
符号的所有后续引用在编译期间被视为sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;
。这就是为什么出现编译器错误的原因。如果在
vcl.h
之前包含strsafe.h
,则首先包含dstring.h
,因此编译器会看到AnsiString::sprintf()
方法的正确声明,然后在编译器看到strsafe.h
代码之前就将Unit1.h
包含在内(大概是Timer1Timer()
),因此对AnsiString().sprint("%i",i)
的调用实际上是在尝试调用AnsiString().sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;("%i",i)
,但失败。当交换
vcl.h
和dshow.h
include时,在包括#define sprintf
之前先处理strsafe.h
中的dstring.h
语句,因此编译器会在AnsiString::sprintf()
中看到dstring.h
方法的以下声明,并且失败:AnsiString& __cdecl sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;(const char* format, ...); // Returns *this
为防止此行为,您可以在
#undef sprintf
之后使用#include <dshow.h>
语句,如JeffRSon建议的那样。但是,正确的解决方案是在STRSAFE_NO_DEPRECATE
之前定义#include <strsafe.h>
。您可以通过以下任一方法来做到这一点:#define STRSAFE_NO_DEPRECATE
语句#include <dshow.h>
添加到您的代码中STRSAFE_NO_DEPRECATE
。 在MSDN上描述了此解决方案:
About Strsafe.h
另一个受支持的解决方案是,在
NO_DSHOW_STRSAFE
之前定义#include <dshow.h>
,以便由于strsafe.h
中的以下代码而不再包括dshow.h
:#ifndef NO_DSHOW_STRSAFE
#define NO_SHLWAPI_STRFCNS
#include <strsafe.h>
#endif
关于c++ - 包括DShow.h会破坏BDS2006上的VCL AnsiString::sprintf(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40000171/