C++ 包括DShow.h会在BDS2006上破坏VCL AnsiString::sprintf()
我终于有时间升级我的视频捕获课程了。我想比较一下VFW(到目前为止我一直使用的)和DirectShow。正如所料,DirectShow速度更快,但当我添加信息文本时,突然C++ 包括DShow.h会在BDS2006上破坏VCL AnsiString::sprintf(),c++,c++builder,directshow,ansistring,C++,C++builder,Directshow,Ansistring,我终于有时间升级我的视频捕获课程了。我想比较一下VFW(到目前为止我一直使用的)和DirectShow。正如所料,DirectShow速度更快,但当我添加信息文本时,突然AnsiString::sprint()不再是AnsiString的成员 经过一番努力,我找到了一个变通方法,即AnsiString::printf()仍然有效,但我很好奇如何解决这个问题。可能一些来自dshow.h和dstring.h的定义相互冲突 我减少了所有不必要的代码以显示此问题: /$$----表格CPP---- //
AnsiString::sprint()
不再是AnsiString
的成员
经过一番努力,我找到了一个变通方法,即AnsiString::printf()
仍然有效,但我很好奇如何解决这个问题。可能一些来自dshow.h
和dstring.h
的定义相互冲突
我减少了所有不必要的代码以显示此问题:
/$$----表格CPP----
//---------------------------------------------------------------------------
#包括
#包括
#布拉格语hdrstop
#包括“Unit1.h”
//---------------------------------------------------------------------------
#pragma包(智能初始化)
#pragma资源“*.dfm”
TForm1*Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent*Owner)
:t表格(所有者)
{
}
//---------------------------------------------------------------------------
void _fastcall TForm1::Timer1Timer(TObject*发送方)
{
静态int i=0;
Caption=AnsiString().sprintf(“%i”,i);//这不起作用
AnsiString s;s.printf(“%i”,i);Caption=s;//这确实有效
i++;
}
//---------------------------------------------------------------------------
它只是一个简单的VCL表单应用程序,上面有一个TTimer
。TTimer
递增计数器i
,并将其输出到表单的标题中。DirectXlib甚至没有链接,只包含了标题
链接器输出错误:
[C++ Error] Unit1.cpp(20): E2316 'sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA' is not a member of 'AnsiString'
如果我交换vcl.h
和dshow.hincludes,编译器将在这一行的
dstring.h`中停止:
AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
出现此错误消息时:
[C++ Error] dstring.h(59): E2040 Declaration terminated incorrectly
因此,显然存在一些冲突(问题在于ansisting
关键字)。将dshow.h
放入命名空间中也没有帮助
有人有什么线索吗
Q1。如何解决此问题?
Q2。究竟是什么/在哪里造成的?
我能想到并且应该有效的唯一解决方案(但如果可以的话,我想避免它)是使用DirectShow内容创建一个OBJ(或DLL),然后将其链接到一个标准的VCL项目中,而不在其中包含dshow.h
,当然,导出也必须没有任何有趣的东西。我没有这个版本的dshow.h和dstring.h,所以我自己无法检查它,但从您引用的错误消息来看,似乎在dshow.h或其依赖项的某个地方,它们声明了一个“sprintf”宏。如果你能找到它,你可以去看看
为了防止这种行为,您需要删除此宏。使用
#undef sprintf
在包含dshow.h.的行之后,问题不在于dshow.h
本身,而在于strsafe.h
本身,而dshow.h
默认包含该行
strsafe.h
包含以下代码1:
1对于许多其他不推荐使用的“不安全”C函数,也有类似的#pragma
和#define
语句
如果未定义STRSAFE\u NO\u DEPRECATE
和DEPRECATE\u SUPPORTED
(在这种情况下是这样),则使用\define sprintf
会导致对任何类型的sprintf
符号的所有后续引用被视为sprintf\u而不是使用在编译过程中
这就是为什么会出现编译器错误。当vcl.h
包含在strasfe.h
之前时,dstring.h
首先被包含,因此编译器会看到AnsiString::sprintf()
方法的正确声明,然后strasfe.h
在编译器看到您的Timer1Timer()之前被包含(可能是通过Unit1.h
)
code,因此您对AnsiString()的调用。sprint(“%i”,i)
实际上是在尝试调用AnsiString()。sprintf\u使用\u StringCchPrintfA\u或\u StringCbPrintfA;(“%i”,i)
,失败
当您交换vcl.h
和dshow.h
includes时,strasfe.h
中的#define sprintf
语句在包含dstring.h
之前得到处理,因此编译器在dstring.h
中看到anstring::sprintf()
方法的以下声明并失败:
AnsiString& __cdecl sprintf_instead_use_StringCchPrintfA_or_StringCbPrintfA;(const char* format, ...); // Returns *this
为了防止这种行为,您可以像Jefferson建议的那样,在#include
之后使用#undef sprintf
语句。然而,正确的解决方案是在包含之前定义STRSAFE\u NO\u DEPRECATE
。您可以通过以下两种方式之一实现:
将#define STRSAFE_NO_DEPRECATE
添加到#include
语句之前的代码中
将STRSAFE\u NO\u DEPRECATE
添加到项目选项中的条件列表中
此解决方案在MSDN上有描述:
- 在文件中包含Strsafe.h时,将不推荐使用由Strsafe.h函数替换的旧函数。尝试使用这些旧函数将导致编译器错误,提示您使用新函数。如果要覆盖此行为,请在包含Strsafe.h之前包含以下语句
#define STRSAFE_NO_DEPRECATE
#define STRSAFE_NO_CB_FUNCTIONS
#define STRSAFE_NO_CCH_FUNCTIONS
- 要仅允许字符计数函数,请在包含Strsafe.h之前包含以下语句
#define STRSAFE_NO_DEPRECATE
#define STRSAFE_NO_CB_FUNCTIONS
#define STRSAFE_NO_CCH_FUNCTIONS
- 要仅允许字节计数函数,请在包含Strsafe.h之前包含以下语句
#define STRSAFE_NO_DEPRECATE
#define STRSAFE_NO_CB_FUNCTIONS
#define STRSAFE_NO_CCH_FUNCTIONS
另一个受支持的解决方案是在之前定义NO\DSHOW\STRSAFE