S60 Open C
Intermixing C and C++

Intermixing C and C++

Table of Contents

extern "C" and Symbian DEF files
Rule for using extern "C"
Example code
Building for WINSCW
Building for ARMv5

 


extern "C" and Symbian DEF files

This article gives a general idea about the Symbian DEF file. Whenever developers write any DLLs that export a set of APIs to the user, there will be an entry for each exported API in the DEF file created. The developer will use:

  • IMPORT_C while declaring exported APIs
  • EXPORT_C while defining such APIs

After building the application for the first time, it will list all the newly exported APIs. After doing a freeze (for which the abld freeze winscw and abld freeze armv5 commands are used), the DEF files will be created under BWINS and EABI folders within the project directory. These DEF files are used to create .lib files for DLLs. In the DEF file, for each exported API, there will be mapping between its prototype and a number will be present.

Let's assume that directory structure used for implementing a library is as shown below:

  • LibraryName\group -- bld.inf and LibraryName.mmp (all build-related files)
  • LibraryName\inc -- All project-specific headers (user include headers)
  • LibraryName\src -- All project-specific source files

If a developer is building the library for the first time, the developer should follow these steps and give the following commands from LibraryName\group:

  1. Create the abld.bat file for the project.
    LibraryName\group>bldmake bldfiles
  2. Builds the project for the default platform (which will be WINSCW and ARMV5).
    LibraryName\group>abld build
  3. Create the DEF file for the default platform (LibraryName\BWINS\LibraryNameu.def and LibraryName\EABI\LibraryNameu.def).
    LibraryName\group>abld freeze
  4. Create .lib files for the DLL using DEF file entries. (LibraryName.lib)
    LibraryName\group> abld build

The final step is required since applications that link with this library (LibraryName.DLL) will link with LibraryName.lib during link time. If the developer fails to perform the final step, the application will get a linker error because there is no LibraryName.lib present.

 


Rule for using extern "C"

When porting or writing libraries that export C APIs to the user, care should be taken to ensure that extern "C" is used properly if those APIs are implemented in a C++ source file. Otherwise these libraries may either not be built for the target platform (ARMV5) or the user of such library will get a linker error when using exported APIs of such library.

If extern "C" is declared in the header and not defined in the source, then after building the library there will be a similar entry in DEF files. The compiler will not give external linkage to these APIs. This can be observed when trying to use these APIs from some other C source file. To overcome this, extern "C" must be present in both declarations and definitions.

 


Example code

/*File: SampleDLL.h*/
/*extern "C" is not used for declaration!*/ 
#ifndef SAMPLEDLL_H
#define SAMPLEDLL_H

typedef int MyInt;
typedef int (*MyFunPtr) ();

IMPORT_C int MyLibLibFun1(MyInt aParam);
IMPORT_C int MyLibLibFun3(MyFunPtr);
IMPORT_C int MyLibLibFun2(int (*MyFun1)());

#endif /*SAMPLEDLL_H*/



//File: SampleDLL.cpp
#include "SampleDLL.h"
// extern "C" is used for definition
extern "C"  {

EXPORT_C int MyLibLibFun1(MyInt aParam)
   {
   return aParam + 10;
   }

EXPORT_C int MyLibLibFun2(int (*MyFun1)())
   {
   return MyFun1();
   }

EXPORT_C int MyLibLibFun3(MyFunPtr aPtr)
   {
   return aPtr();
   }
}

 


Building for WINSCW

This code will get compiled for WINSCW. The DEF file for WINSCW will have the following entries:

EXPORTS
     [email protected]@[email protected] @ 1 NONAME ; int MyLibLibFun1(int)
     [email protected]@[email protected] @ 2 NONAME ; int MyLibLibFun2(int (*)(void))
     [email protected]@[email protected] @ 3 NONAME ; int MyLibLibFun3(int (*)(void)) 

Even if we comment extern "C" from the above SampleDLL.cpp file, we will have the same DEF file entries.

 


Building for ARMv5

If we try the above code without extern "C" in SampleDLL.cpp, the code will get built and the DEF file entry for ARMv5 will be:

EXPORTS
     _Z12MyLibLibFun1i @ 1 NONAME
     _Z12MyLibLibFun2PFivE @ 2 NONAME
     _Z12MyLibLibFun3PFivE @ 3 NONAME  

If we keep the extern "C" in SampleDLL.cpp, this code will not get compiled for ARMv5 and will result in the error given below:

"..\src\Sampledll.cpp", line 7: Error:  #337: linkage specification is incompatible with previous "MyLibLibFun1" (declared at line 9 of "..\inc\SampleDLL.h")
   EXPORT_C int MyLibLibFun1(MyInt aParam)
                ^ 
"..\src\Sampledll.cpp", line 17: Error:  #337: linkage specification is incompatible with previous "MyLibLibFun3" (declared at line 11 of "..\inc\SampleDLL.h")
   EXPORT_C int MyLibLibFun3(MyFunPtr aPtr)
               ^

The reason for the errors is that MyLibLibFun1 and MyLibLibFun3 use typedef datatypes. There is no issue with MyLibLibFun2() since it does not use typedef datatypes. To overcome these errors, we have to keep both the declaration and the definition within extern "C" linkage.

/*File: SampleDLL.h*/    
#ifndef SAMPLEDLL_H  
#define SAMPLEDLL_H  
/*extern "C" is used for declaration also*/

typedef int MyInt;  
typedef int (*MyFunPtr) ();    

#ifdef __cplusplus  
extern "C" {  
#endif //__cplusplus    

IMPORT_C int MyLibLibFun1(MyInt aParam);  
IMPORT_C int MyLibLibFun3(MyFunPtr);  
IMPORT_C int MyLibLibFun2(int (*MyFun1)());    

#ifdef __cplusplus  
}  
#endif //__cplusplus    

#endif /*SAMPLEDLL_H*/ 

When everything is within extern "C" (extern "C" in header and implementation), the DEF file for ARMv5 and WINSCW looks as follows:

EXPORTS
    MyLibLibFun1 @ 1 NONAME
    MyLibLibFun2 @ 2 NONAME
    MyLibLibFun3 @ 3 NONAME 

So, as one can observe in the above section where different DEF file entries are created with and without extern "C", we should make sure that the rule is followed. extern "C" has to be used in both declaration and definition: otherwise we will either not be able to build it for all the platforms or it will not be possible to use those exported C APIs in other applications.

Give feedback of this section


©Nokia 2007

Back to top


This material, including documentation and any related computer programs, is protected by copyright controlled by Nokia. All rights are reserved. Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior written consent of Nokia. This material also contains confidential information, which may not be disclosed to others without the prior written consent of Nokia.

Nokia is a registered trademark of Nokia Corporation. S60 and logo is a trademark of Nokia Corporation. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. Other company and product names mentioned herein may be trademarks or tradenames of their respective owners.