C++ 包括DShow.h会在BDS2006上破坏VCL AnsiString::sprintf()

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---- //

我终于有时间升级我的视频捕获课程了。我想比较一下VFW(到目前为止我一直使用的)和DirectShow。正如所料,DirectShow速度更快,但当我添加信息文本时,突然
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.h
includes,编译器将在这一行的
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