diff -r 43e37759235e -r 51a74ef9ed63 Symbian3/SDK/Source/GUID-E2B67F14-EC4E-41B6-9F8E-AB58B9E8D7B6.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/SDK/Source/GUID-E2B67F14-EC4E-41B6-9F8E-AB58B9E8D7B6.dita Wed Mar 31 11:11:55 2010 +0100 @@ -0,0 +1,156 @@ + + + + + +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 lists 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. +
  3. Build the project for +the default platform (which will be WINSCW and ARMV5).

    LibraryName\group>abld build
  4. +
  5. Create the DEF file +for the default platform (LibraryName\BWINS\LibraryNameu.def and +LibraryName\EABI\LibraryNameu.def).

    LibraryName\group>abld freeze
  6. +
  7. Create .lib files +for the DLL using DEF file entries. (LibraryName.lib)

    LibraryName\group> abld build
  8. +
+

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 + ?MyLibLibFun1@@YAHH@Z @ 1 NONAME ; int MyLibLibFun1(int) + ?MyLibLibFun2@@YAHP6AHXZ@Z @ 2 NONAME ; int MyLibLibFun2(int (*)(void)) + ?MyLibLibFun3@@YAHP6AHXZ@Z @ 3 NONAME ; int MyLibLibFun3(int (*)(void))

If +the user comments extern "C" from the above SampleDLL.cpp file, +the DEF file entries will be the same.

Building for ARMv5

If +the user try's 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 the user keeps 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, +the user must 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", the user must make sure that the rule is followed. extern "C" has to +be used in both declaration and definition: otherwise the user 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.

+
\ No newline at end of file