Developer Area Developer Area
www.be.com

Becoming A Be Developer

Becoming A Be Developer

Join Registered Developer Program

Registered Developer Area

Developer Library

Marketing Resources

Developer Events

Search Contact


Release 4 Coding Issues

Necessary code changes to support the new binary format and developer tools.

How long will it take to move my Application from R3 to R4?

It really depends on your code, and how many of the items listed below need to be fixed. Internally some applications were a simple recompile, others took a couple days to fix. In general this should take a great deal less time than earlier binary compatibility changes, as the APIs themselves are not changing. Of course if you have an application that uses the old Media Kit, or if you want to add Media Kit functionality, those changes could be more substantial.

Development Environment

Tool location

With the introduction of the EGCS tools a new location for tools was needed (/boot/apps/Metrowerks/ didn't seem like the best place anymore.) Now all development tools will be located in a sub-directory of /boot/develop/tools/. The tools that will ship with R4 will be located as follows:
 
   EGCS:                   /boot/develop/tools/gnupro/             (Intel Only) 
   Metrowerks:             /boot/develop/tools/Metrowerks/         (PowerPC Only) 
   PackageBuilder:         /boot/develop/tools/PackageBuilder/ 

Exporting Symbols
In Release 3 symbols were exported from binaries in one of three ways:

   #pragma export on/reset 
   __declspec(dllexport) 
   Export files listing all symbols to be exported 
With the move to ELF we have a new recommended method: _EXPORT. Simply add _EXPORT before a function or class declaration and your compiler will do the right thing. See below for examples.

Shared Libraries
Linking against a shared lib in R3 Intel required linking against a .LIB file that defined the library's exported symbols. This was an artifact of the PE binary format.

In R4 Intel and ELF you link against the run-time library itself, just like you do in PowerPC. This will require modification of most makefiles and BeIDE projects to link against the appropriate items.

Shared Library Location: 
                /boot/develop/lib/x86/ 
                /boot/develop/lib/ppc/ 
Links to the run-time libraries and Be provided static libraries and objects are located in these folders.

Code Changes

Remove all #pragma options
#pragmas are compiler specific and should not be used in your code. We have suggestions for cleaning up your code and replacing #pragmas with safety. These suggestions work on both PowerPC and Intel.

#pragma once This is used to make sure that a given header file is only defined once in the compile process. You can get the equivalent functionality using #defines.

 
                Replace: 
                        /* MyHeader.h */ 
                        #pragma once 
                        /* definitions follow */ 
                With: 
                        /* MyHeader.h */ 
                        #ifndef MY_HEADER_H 
                        #define MY_HEADER_H 
                        /* definitions follow */ 
                        #endif 
This allows you to simply include the appropriate header file in any other file and the compiler will make sure it is only included once.

#pragma unused Used to clear warnings from implementations of functions that do not use all of the parameters passed in. BeBuild.h defines a macro _UNUSED that will make the parameter invisible to the Metrowerks compiler to stop warnings.

 
         Replace: 
                 my_function(int32 foo, int32 blah) { 
                 #pragma unused blah; 
                 } 
                
         With: 
                 my_function(int32 foo, int32 _UNUSED(blah)) { 
                   
                 } 

#pragma export Used to specify that a symbol needs to be exported from a given binary. It can be replaced by the _EXPORT macro.

 
         Replace: 
                 #pragma export on 
                 int32 my_function(); 
                 #pragma export reset 
                       
                 #pragma export on 
                 class my_class; 
                 #pragma export reset 
         With: 
                 _EXPORT int32 my_function(); 
                 _EXPORT class my_class; 

Including the Proper Headers
One major change with the switch to EGCS is the loss of the ability to use a precompiled header file. With CodeWarrior it was possible to precompile a file that includes all of the headers you need. While this feature reduces compilation time, it leads to source code that does not #include all of the files needed to compile. Developers who did not #include all needed headers will need to go back through all of their code and adjust them.

Errors reported that might be a result of improperly included header files are:

  • Can't find Header File
    This is generally a result of using "header.h" or when the other is warranted.
  • Incomplete class definition.
  • Cannot find matching function, closest match is X.
    This usually occurs when a function accepts a base class and you have not included the appropriate sub-class' header file. The compiler has no way to know that the sub is an instance of the base.
  • No member named foo.
    The struct or class has a member whose header file has not been included.

Structure Definitions

 
         Replace: 
                 struct fig { 
                 int bar; 
                 char blat[]; 
                }; 
         With: 
                struct fig { 
                int bar; 
                char blat[0]; 
                }; 

Const variables
Be sure to pass items with proper constness to C++ functions. We suggest you do this by creating the variable as a const rather than casting to a const variable, as that might allow you to modify memory you are forbidden to touch.

 
                Replace: 
                char *foo; 
                message->FindString("foo", &foo); 
                
                With: 
                const char *foo; 
                message->FindString("foo", &foo); 
                
                We Advise Against Using: 
                char *foo; 
                message->FindString("foo", (const char **)&foo); 

BMessage::FindPointer() && BMessage::FindData()
Both of these functions take a void ** as a parameter that will be filled in with the appropriate pointer. gcc is very strict that a pointer to void * is different from a pointer to char *. Thus you will need to explicitly cast to void ** in these functions.

 
         Replace: 
         BMenuItem *item; 
         message->FindPointer("item", &item); 
                
         const node_ref *node; 
         ssize_t numBytes; 
         message->FindData("node", B_RAW_TYPE, &node, &numBytes); 
              
         With: 
         BMenuItem *item; 
         message->FindPointer("item", (void **)&item); 
                
         const node_ref *node; 
         ssize_t numBytes; 
         message->FindData("node", B_RAW_TYPE, 
         (void **)&node, &numBytes); 

inherited
As mentioned when switching to R3, the inherited keyword did not make it into the ANSI C++ specification. As such it should be removed from all code. The Metrowerks compilers still can accept inherited through a command-line option, but gcc will not accept it. Replace the inherited keyword with the explicit class or create a private typedef _inherited that represents the base class.

 
         Replace: 
                 class foo { 
                 public: 
                 int32 my_function(); 
                 } 
                 
                 class bar : public foo { 
                 public: 
                 int32 my_function(); 
                 } 
                        
                 bar::my_function() { 
                 inherited::my_function() 
                 /* the rest of my code */ 
                 } 

         With: 
                 class foo { 
                 public: 
                 int32 my_function(); 
                 } 
                        
                 class bar : public foo { 
                 public: 
                 int32 my_function(); 
                 } 
                        
                 bar::my_function() { 
                 foo::my_function() 
                 /* the rest of my code */ 
                 } 
                
         Or 
                 class foo { 
                 public: 
                 int32 my_function(); 
                 } 
                        
                 class bar : public foo { 
                 public: 
                 int32 my_function(); 
                                        
                 private: 
                 typedef foo _inherited; 
                 } 
                        
                 bar::my_function() { 
                 _inherited::my_function() 
                 /* the rest of my code */ 
                 } 


Back to the Switch

 

The BeOS News and Events Developers User Groups Support BeStore BeWare

Copyright ©1999 Be, Inc. Be, BeOS, and the Be and BeOS logos are registered trademarks, and BeBox, BeWare, GeekPort are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com. Icons used herein are the property of Be Inc. All rights reserved.