Symbian3/SDK/Source/GUID-E2B67F14-EC4E-41B6-9F8E-AB58B9E8D7B6.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-E2B67F14-EC4E-41B6-9F8E-AB58B9E8D7B6" xml:lang="en"><title>extern
"C" and Symbian DEF files</title><shortdesc/><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>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:</p>
<ul>
<li><p><codeph>IMPORT_C</codeph> while declaring exported APIs</p></li>
<li><p><codeph>EXPORT_C</codeph> while defining such APIs</p></li>
</ul>
<p>After building the application for the first time, it lists all the newly
exported APIs. After doing a freeze (for which the <cmdname>abld freeze winscw</cmdname> and <cmdname>abld
freeze armv5</cmdname> commands are used), the DEF files will be created under <filepath>BWINS</filepath> and <filepath>EABI</filepath> folders
within the project directory. These DEF files are used to create <filepath>.lib</filepath> files
for DLLs. In the DEF file, for each exported API, there will be mapping between
its prototype and a number will be present.  </p>
<p>Let's assume that directory structure used for implementing a library is
as shown below:</p>
<ul>
<li><p><filepath>LibraryName\group</filepath> -- <filepath>bld.inf</filepath> and <filepath>LibraryName.mmp</filepath> (all
build-related files)</p></li>
<li><p><filepath>LibraryName\inc</filepath> -- All project-specific headers
(user include headers)</p></li>
<li><p><filepath>LibraryName\src</filepath> -- All project-specific source
files </p></li>
</ul>
<p>If a developer is building the library for the first time, the developer
should follow these steps and give the following commands from <filepath>LibraryName\group</filepath>: </p>
<ol>
<li id="GUID-DE29CFD9-77C2-4790-89C6-5491F3EBA922"><p>Create the <filepath>abld.bat</filepath> file
for the project. </p><codeblock xml:space="preserve">LibraryName\group&gt;bldmake bldfiles</codeblock></li>
<li id="GUID-DC6AE0F4-64C6-432B-826B-26B7CDA8565C"><p>Build the project for
the default platform (which will be <codeph>WINSCW</codeph> and <codeph>ARMV5</codeph>). </p><codeblock xml:space="preserve">LibraryName\group&gt;abld build</codeblock></li>
<li id="GUID-836865DB-F613-4000-95AC-DDC9E3F498B2"><p>Create the DEF file
for the default platform (<filepath>LibraryName\BWINS\LibraryNameu.def and
LibraryName\EABI\LibraryNameu.def</filepath>). </p><codeblock xml:space="preserve">LibraryName\group&gt;abld freeze</codeblock></li>
<li id="GUID-C69111BA-1568-4CB4-8AB5-0EDEFC854D39"><p>Create <filepath>.lib</filepath> files
for the DLL using DEF file entries. (<filepath>LibraryName.lib</filepath>) </p><codeblock xml:space="preserve">LibraryName\group&gt; abld build</codeblock></li>
</ol>
<p>The final step is required since applications that link with this library
(<filepath>LibraryName.DLL</filepath>) will link with <filepath>LibraryName.lib</filepath> during
link time. If the developer fails to perform the final step, the application
will get a linker error because there is no <filepath>LibraryName.lib</filepath> present.</p>
<section id="GUID-3AD1D783-C36F-4443-8957-6DB9434927B5">       <title>Rule
for using extern "C"</title>       <p>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.  </p><p>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.</p><p><b>Example
code</b></p><codeblock xml:space="preserve">/*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();
   }
}
</codeblock><p><b>Building for <codeph>WINSCW</codeph></b></p><p>This code
will get compiled for <codeph>WINSCW</codeph>. The DEF file for <codeph>WINSCW</codeph> will
have the following entries:</p><codeblock xml:space="preserve">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)) </codeblock><p>If
the user comments extern "C" from the above <filepath>SampleDLL.cpp</filepath> file,
the DEF file entries will be the same.</p><p><b>Building for <codeph>ARMv5</codeph></b></p><p>If
the user try's the above code without extern "C" in <filepath>SampleDLL.cpp</filepath>,
the code will get built and the DEF file entry for <codeph>ARMv5</codeph> will
be:</p><codeblock xml:space="preserve">EXPORTS
     _Z12MyLibLibFun1i @ 1 NONAME
     _Z12MyLibLibFun2PFivE @ 2 NONAME
     _Z12MyLibLibFun3PFivE @ 3 NONAME  </codeblock><p>If the user keeps the
extern "C" in <filepath>SampleDLL.cpp</filepath>, this code will not get compiled
for <codeph>ARMv5</codeph> and will result in the error given below:  </p><codeblock xml:space="preserve">"..\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)
               ^</codeblock><p>The reason for the errors is that <codeph>MyLibLibFun1</codeph> and <codeph>MyLibLibFun3</codeph> use <codeph>typedef</codeph> datatypes. There is no issue with <codeph>MyLibLibFun2()</codeph> since
it does not use <codeph>typedef</codeph> datatypes. To overcome these errors,
the user must keep both the declaration and the definition within extern "C"
linkage.</p><codeblock xml:space="preserve">/*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*/ </codeblock><p>When everything is within extern "C"
(extern "C" in header and implementation), the DEF file for <codeph>ARMv5</codeph> and <codeph>WINSCW</codeph> looks
as follows:</p><codeblock xml:space="preserve">EXPORTS
    MyLibLibFun1 @ 1 NONAME
    MyLibLibFun2 @ 2 NONAME
    MyLibLibFun3 @ 3 NONAME </codeblock><p>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. </p>     </section>
</conbody></concept>