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
:
Create the abld.bat
file
for the project.
LibraryName\group>bldmake bldfiles
Build the project for
the default platform (which will be WINSCW
and ARMV5
).
LibraryName\group>abld build
Create the DEF file
for the default platform (LibraryName\BWINS\LibraryNameu.def and
LibraryName\EABI\LibraryNameu.def
).
LibraryName\group>abld freeze
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.
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.