В том числе DShow.h ломает VCL AnsiString :: sprintf () на BDS2006

Наконец-то у меня появилось время обновить класс захвата видео. Я хотел сравнить 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 libs даже не связаны, только заголовки включены!

Линкер выводит ошибку:

[C++ Error] Unit1.cpp(20): E2316 'sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA' is not a member of 'AnsiString'

Если я поменяю vcl.h и dshow.hincludes, the compiler stops indstring.h` в этой строке:

AnsiString& __cdecl         sprintf(const char* format, ...); // Returns *this

С этим сообщением об ошибке:

[C++ Error] dstring.h(59): E2040 Declaration terminated incorrectly

Таким образом, существует определенный конфликт ( AnsiString Ключевое слово является проблемой). Ввод dshow.h в namespace тоже не помогает.

У кого-нибудь есть какие-нибудь подсказки?

Q1. Как это исправить?

Q2. Что / где именно это вызывает?

Единственное решение, о котором я могу думать и которое должно работать (но я хочу избежать этого, если смогу), — это создать OBJ (или же DLL) с DirectShow вещи, а затем связать это в стандарт VCL проект без включения dshow.h в этом, и, конечно, экспорт должен быть без каких-либо забавных вещей, тоже.

1

Решение

Проблема не с 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 Есть похожие #pragma а также #define операторы для многих других устаревших «небезопасных» функций C.

Если оба 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 включает в себя, #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>как предложил Джеффрсон. Тем не менее правильный Решение состоит в том, чтобы определить STRSAFE_NO_DEPRECATE до #include <strsafe.h>, Вы можете сделать это одним из следующих способов:

  1. добавление #define STRSAFE_NO_DEPRECATE в ваш код до #include <dshow.h> заявление

  2. добавление STRSAFE_NO_DEPRECATE в список Условий в опциях вашего проекта.

Это решение описано в MSDN:

О Strsafe.h

  • Когда вы включаете в свой файл Strsafe.h, более старые функции, замененные функциями Strsafe.h, будут устаревшими. Попытки использовать эти старые функции приведут к ошибке компилятора, говорящей вам использовать более новые функции. Если вы хотите переопределить это поведение, включите следующий оператор перед включением Strsafe.h.

    #define STRSAFE_NO_DEPRECATE
    
  • Чтобы разрешить только функции подсчета символов, включите следующий оператор перед тем, как включать Strsafe.h.

    #define STRSAFE_NO_CB_FUNCTIONS
    
  • Чтобы разрешить только функции подсчета байтов, перед включением Strsafe.h включите следующую инструкцию.

    #define STRSAFE_NO_CCH_FUNCTIONS
    

Другое поддерживаемое решение — определить NO_DSHOW_STRSAFE до #include <dshow.h> так что это не будет включать strsafe.h больше, благодаря этому коду в dshow.h:

#ifndef NO_DSHOW_STRSAFE
#define NO_SHLWAPI_STRFCNS
#include <strsafe.h>
#endif
1

Другие решения

У меня нет этой самой версии dshow.h и dstring.h, поэтому я не могу проверить это сам, но из сообщений об ошибках, которые вы цитируете, кажется, что где-то в dshow.h или его зависимостях они объявляют макрос «sprintf». Вы можете посмотреть, если вы можете найти это.

Чтобы предотвратить такое поведение, вам нужно удалить этот макрос. использование

#undef sprintf

после строки, включающей dshow.h.

1

По вопросам рекламы [email protected]