Menu

Problem with stream classes in Visual Studio

gobrad
2007-09-04
2012-09-25
  • gobrad

    gobrad - 2007-09-04

    Hello

    I am trying to convert a large project from BCB++ 4.0 (OWL 2) to the OwlNext and Visual Studio 2003. I am using the latest OwlNext, 6.20.3 and OwlExt. OwlNext is simply installed by using installer from CodeGear website.

    Most of the code now compiles, but I am stuck with compiler errors in geometry.h. I suppose it has something to do with new stream classes in OwlNext and/or namespaces, but have no idea how to solve it. VS Project defines are currently only: USE_OWLEXTLIB and OWL2_COMPAT.

    Here are the compiler errors:

    d:\OWL\include\owl\geometry.h(157) : error C2143: syntax error : missing ';' before '&'
    d:\OWL\include\owl\geometry.h(157) : error C2501: 'ipstream' : missing storage-class or type specifiers
    d:\OWL\include\owl\geometry.h(157) : error C2065: 'is' : undeclared identifier
    d:\OWL\include\owl\geometry.h(157) : error C2065: 'p' : undeclared identifier
    d:\OWL\include\owl\geometry.h(157) : error C2275: 'OWL::TPoint' : illegal use of this type as an expression
    d:\OWL\include\owl\geometry.h(123) : see declaration of 'OWL::TPoint'
    d:\OWL\include\owl\geometry.h(157) : warning C4229: anachronism used : modifiers on data are ignored
    d:\OWL\include\owl\geometry.h(157) : error C2501: 'operator>>'' : missing storage-class or type specifiers d:\OWL\include\owl\geometry.h(157) : error C2078: too many initializers d:\OWL\include\owl\geometry.h(158) : error C2365: 'OWL::operator>>'' : redefinition; previous definition was a 'data variable'
    d:\OWL\include\owl\geometry.h(157) : see declaration of 'OWL::operator`>>''
    ......................

    Can anybody help?

    Thanks in advance,
    Goran Obradovic

     
    • gobrad

      gobrad - 2007-09-05

      Hi Vidar

      Thank you very much for this comprehensive analysis. I already implemented similar solution as a quick-fix and it is working well.

      Regards,
      Goran Obradovic

       
    • Vidar Hasfjord

      Vidar Hasfjord - 2007-09-04

      Hi Goran,

      Line 157 in <owl/geometry.h>:

      _OWLCFUNC(ipstream&) operator >>(ipstream& is, TPoint& p);

      after macro preprosessing (usually) expands to

      ipstream& __cdecl operator >>(ipstream& is, TPoint& p);

      The error messages you get indicate that "ipstream" is not yet defined. Normally "ipstream" should have already been declared in <owl/objstrm.h> which is included at line 21 in <owl/geometry.h>.

      Is "UNIX" defined as a symbol in your project somewhere? This will prevent <owl/objstrm.h> from being included. (Sidebar: This seems nonsensical by OWLNext; there's no alternative handling for the "UNIX" symbol that makes the code compile, unless "__HPUX_SOURCE" is also defined, which includes <owl/objstrm.h> in a separate but identical include statement!).

      Check out why <owl/objstrm.h> is not included. Running <owl/geometry.h> through the preprocessor and inspecting the output may help (use the same build configuration and defines).

      Regards,
      Vidar Hasfjord

       
    • gobrad

      gobrad - 2007-09-04

      Hi Vidar

      Thank you for a quick answer.

      Actually, I followed the same logic and, as a first step, removed all conditionals when including <owl/objstrm.h> from geometry.h. No success.

      Then, I created a Test.cpp in my project, containing only one line, #include <owl/geometry.h>. Compiling this file brings the same errors. After adding #include <owl/defs.h> before #include <owl/geometry.h>, Test.cpp compiles without errors. So, it seems that geometry.h needs defs.h settings in order to compile. But, "geometry.h" contains only #include <owl/private/defs.h> instead. What is the role of headers in "private" directory?

      Is there some article or examples for using OwlNext with VS 7?

      Regards
      Goran Obradovic

       
      • Vidar Hasfjord

        Vidar Hasfjord - 2007-09-05

        Hi Goran,

        I've investigated this problem in depth now, and it looks like you've run into a design flaw in the OWLNext headers. There is an indirect circular dependency between <owl/geometry.h> and <owl/objstrm.h> (through <owl/defs.h> which includes <owl/wsyscls.h> which again depend on and include <owl/geometry.h>).

        It seems some OWL developer circumvented the circular dependency problem by creating an awful loophole in the sentry guard in <owl/geometry.h>:

        if !defined(OWL_GEOMETRY_H) || defined(WSYSCLS_ENTRY)

        Note the second term. This exists just to allow <owl/wsyscls.h> a second pass through this header. Here is how it is set up in <owl/wsyscls.h> (some comments and blank lines removed for clarity):

        define WSYSCLS_ENTRY

        if !defined(OWL_GEOMETRY_H) || defined(WSYSCLS_ENTRY)

        include <owl/geometry.h> // TPoint, et. al.

        endif

        undef WSYSCLS_ENTRY

        In fact, the content of the whole <owl/geometry.h> header is not processed if not through this loophole. Below the includes in <owl/geometry.h> you'll find:

        if defined(WSYSCLS_ENTRY)

        define ENTRY

        endif

        if defined(ENTRY)

        The rest of the file is encapsulated in that #if statement!

        Unfortunately this is brittle and only solves the circular dependency in certain cases that is highly dependent on the order files are included. Basically the <owl/geometry.h> header is fundamentally broken; it is not self-sufficient. It only works properly when it's included from <owl/wsyscls.h>, i.e. you can only include <owl/geometry.h> via <owl/wsyscls.h> (directly or indirectly). Including <owl/geometry.h> explicitly will either fail (if <owl/wsyscls.h> has not already been included) or be a no-operation (in case <owl/wsyscls.h> has already been included, which means <owl/geometry.h> has already been included also).

        Like you've already discovered you can circumvent the problem by including <owl/defs.h> (which includes <owl/wsyscls.h>) before <owl/geometry.h>:

        include <owl/defs.h>

        include <owl/geometry.h> // technically a no-op, but future-proof

        While including <owl/geometry.h> here is technically a no-op, I still recommend doing so to be compatible with potential future OWLNext fixes to this problem. Including <owl/wsyscls.h> before <owl/geometry.h> will work as well, of course, but semantically less elegant; in the future this problem may be fixed and you then probably don't want the extra definition in <owl/wsyscls.h>.

        Here's a proposal to fix this in OWLNext:

        Remove the <owl/wsyscls.h> include from <owl/defs.h>. It is not needed in general by all OWL programs and doesn't belong in this header. Then close the sentry guard loophole in <owl/geometry.h> and remove the application of the loophole in <owl/wsyscls.h>. Add <owl/wsyscls.h> includes to only the headers in OWL that strictly need it; as far as I can tell, that is just <owl/module.h>.

        I've applied this fix to my private OWLNext build, and my simple tests so far compile with no errors or warnings.

        > What is the role of headers in "private" directory?

        As far as I know, the "private" directory is for compiler/platform-specific code, but I think more code lives there as well; for no apparent reason.

        Regards,
        Vidar Hasfjord

         

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB