|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-E2B67F14-EC4E-41B6-9F8E-AB58B9E8D7B6" xml:lang="en"><title>extern |
|
13 "C" and Symbian DEF files</title><shortdesc/><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>This article gives a general idea about the Symbian DEF file. Whenever |
|
15 developers write any DLLs that export a set of APIs to the user, there will |
|
16 be an entry for each exported API in the DEF file created. The developer will |
|
17 use:</p> |
|
18 <ul> |
|
19 <li><p><codeph>IMPORT_C</codeph> while declaring exported APIs</p></li> |
|
20 <li><p><codeph>EXPORT_C</codeph> while defining such APIs</p></li> |
|
21 </ul> |
|
22 <p>After building the application for the first time, it lists all the newly |
|
23 exported APIs. After doing a freeze (for which the <cmdname>abld freeze winscw</cmdname> and <cmdname>abld |
|
24 freeze armv5</cmdname> commands are used), the DEF files will be created under <filepath>BWINS</filepath> and <filepath>EABI</filepath> folders |
|
25 within the project directory. These DEF files are used to create <filepath>.lib</filepath> files |
|
26 for DLLs. In the DEF file, for each exported API, there will be mapping between |
|
27 its prototype and a number will be present. </p> |
|
28 <p>Let's assume that directory structure used for implementing a library is |
|
29 as shown below:</p> |
|
30 <ul> |
|
31 <li><p><filepath>LibraryName\group</filepath> -- <filepath>bld.inf</filepath> and <filepath>LibraryName.mmp</filepath> (all |
|
32 build-related files)</p></li> |
|
33 <li><p><filepath>LibraryName\inc</filepath> -- All project-specific headers |
|
34 (user include headers)</p></li> |
|
35 <li><p><filepath>LibraryName\src</filepath> -- All project-specific source |
|
36 files </p></li> |
|
37 </ul> |
|
38 <p>If a developer is building the library for the first time, the developer |
|
39 should follow these steps and give the following commands from <filepath>LibraryName\group</filepath>: </p> |
|
40 <ol> |
|
41 <li id="GUID-DE29CFD9-77C2-4790-89C6-5491F3EBA922"><p>Create the <filepath>abld.bat</filepath> file |
|
42 for the project. </p><codeblock xml:space="preserve">LibraryName\group>bldmake bldfiles</codeblock></li> |
|
43 <li id="GUID-DC6AE0F4-64C6-432B-826B-26B7CDA8565C"><p>Build the project for |
|
44 the default platform (which will be <codeph>WINSCW</codeph> and <codeph>ARMV5</codeph>). </p><codeblock xml:space="preserve">LibraryName\group>abld build</codeblock></li> |
|
45 <li id="GUID-836865DB-F613-4000-95AC-DDC9E3F498B2"><p>Create the DEF file |
|
46 for the default platform (<filepath>LibraryName\BWINS\LibraryNameu.def and |
|
47 LibraryName\EABI\LibraryNameu.def</filepath>). </p><codeblock xml:space="preserve">LibraryName\group>abld freeze</codeblock></li> |
|
48 <li id="GUID-C69111BA-1568-4CB4-8AB5-0EDEFC854D39"><p>Create <filepath>.lib</filepath> files |
|
49 for the DLL using DEF file entries. (<filepath>LibraryName.lib</filepath>) </p><codeblock xml:space="preserve">LibraryName\group> abld build</codeblock></li> |
|
50 </ol> |
|
51 <p>The final step is required since applications that link with this library |
|
52 (<filepath>LibraryName.DLL</filepath>) will link with <filepath>LibraryName.lib</filepath> during |
|
53 link time. If the developer fails to perform the final step, the application |
|
54 will get a linker error because there is no <filepath>LibraryName.lib</filepath> present.</p> |
|
55 <section id="GUID-3AD1D783-C36F-4443-8957-6DB9434927B5"> <title>Rule |
|
56 for using extern "C"</title> <p>When porting or writing libraries that |
|
57 export C APIs to the user, care should be taken to ensure that extern "C" |
|
58 is used properly if those APIs are implemented in a C++ source file. Otherwise |
|
59 these libraries may either not be built for the target platform (ARMV5) or |
|
60 the user of such library will get a linker error when using exported APIs |
|
61 of such library. </p><p>If extern "C" is declared in the header and not defined |
|
62 in the source, then after building the library there will be a similar entry |
|
63 in DEF files. The compiler will not give external linkage to these APIs. This |
|
64 can be observed when trying to use these APIs from some other C source file. |
|
65 To overcome this, extern "C" must be present in both declarations and definitions.</p><p><b>Example |
|
66 code</b></p><codeblock xml:space="preserve">/*File: SampleDLL.h*/ |
|
67 /*extern "C" is not used for declaration!*/ |
|
68 #ifndef SAMPLEDLL_H |
|
69 #define SAMPLEDLL_H |
|
70 |
|
71 typedef int MyInt; |
|
72 typedef int (*MyFunPtr) (); |
|
73 |
|
74 IMPORT_C int MyLibLibFun1(MyInt aParam); |
|
75 IMPORT_C int MyLibLibFun3(MyFunPtr); |
|
76 IMPORT_C int MyLibLibFun2(int (*MyFun1)()); |
|
77 |
|
78 #endif /*SAMPLEDLL_H*/ |
|
79 |
|
80 |
|
81 |
|
82 //File: SampleDLL.cpp |
|
83 #include "SampleDLL.h" |
|
84 // extern "C" is used for definition |
|
85 extern "C" { |
|
86 |
|
87 EXPORT_C int MyLibLibFun1(MyInt aParam) |
|
88 { |
|
89 return aParam + 10; |
|
90 } |
|
91 |
|
92 EXPORT_C int MyLibLibFun2(int (*MyFun1)()) |
|
93 { |
|
94 return MyFun1(); |
|
95 } |
|
96 |
|
97 EXPORT_C int MyLibLibFun3(MyFunPtr aPtr) |
|
98 { |
|
99 return aPtr(); |
|
100 } |
|
101 } |
|
102 </codeblock><p><b>Building for <codeph>WINSCW</codeph></b></p><p>This code |
|
103 will get compiled for <codeph>WINSCW</codeph>. The DEF file for <codeph>WINSCW</codeph> will |
|
104 have the following entries:</p><codeblock xml:space="preserve">EXPORTS |
|
105 ?MyLibLibFun1@@YAHH@Z @ 1 NONAME ; int MyLibLibFun1(int) |
|
106 ?MyLibLibFun2@@YAHP6AHXZ@Z @ 2 NONAME ; int MyLibLibFun2(int (*)(void)) |
|
107 ?MyLibLibFun3@@YAHP6AHXZ@Z @ 3 NONAME ; int MyLibLibFun3(int (*)(void)) </codeblock><p>If |
|
108 the user comments extern "C" from the above <filepath>SampleDLL.cpp</filepath> file, |
|
109 the DEF file entries will be the same.</p><p><b>Building for <codeph>ARMv5</codeph></b></p><p>If |
|
110 the user try's the above code without extern "C" in <filepath>SampleDLL.cpp</filepath>, |
|
111 the code will get built and the DEF file entry for <codeph>ARMv5</codeph> will |
|
112 be:</p><codeblock xml:space="preserve">EXPORTS |
|
113 _Z12MyLibLibFun1i @ 1 NONAME |
|
114 _Z12MyLibLibFun2PFivE @ 2 NONAME |
|
115 _Z12MyLibLibFun3PFivE @ 3 NONAME </codeblock><p>If the user keeps the |
|
116 extern "C" in <filepath>SampleDLL.cpp</filepath>, this code will not get compiled |
|
117 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") |
|
118 EXPORT_C int MyLibLibFun1(MyInt aParam) |
|
119 ^ |
|
120 "..\src\Sampledll.cpp", line 17: Error: #337: linkage specification is incompatible with previous "MyLibLibFun3" (declared at line 11 of "..\inc\SampleDLL.h") |
|
121 EXPORT_C int MyLibLibFun3(MyFunPtr aPtr) |
|
122 ^</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 |
|
123 it does not use <codeph>typedef</codeph> datatypes. To overcome these errors, |
|
124 the user must keep both the declaration and the definition within extern "C" |
|
125 linkage.</p><codeblock xml:space="preserve">/*File: SampleDLL.h*/ |
|
126 #ifndef SAMPLEDLL_H |
|
127 #define SAMPLEDLL_H |
|
128 /*extern "C" is used for declaration also*/ |
|
129 |
|
130 typedef int MyInt; |
|
131 typedef int (*MyFunPtr) (); |
|
132 |
|
133 #ifdef __cplusplus |
|
134 extern "C" { |
|
135 #endif //__cplusplus |
|
136 |
|
137 IMPORT_C int MyLibLibFun1(MyInt aParam); |
|
138 IMPORT_C int MyLibLibFun3(MyFunPtr); |
|
139 IMPORT_C int MyLibLibFun2(int (*MyFun1)()); |
|
140 |
|
141 #ifdef __cplusplus |
|
142 } |
|
143 #endif //__cplusplus |
|
144 |
|
145 #endif /*SAMPLEDLL_H*/ </codeblock><p>When everything is within extern "C" |
|
146 (extern "C" in header and implementation), the DEF file for <codeph>ARMv5</codeph> and <codeph>WINSCW</codeph> looks |
|
147 as follows:</p><codeblock xml:space="preserve">EXPORTS |
|
148 MyLibLibFun1 @ 1 NONAME |
|
149 MyLibLibFun2 @ 2 NONAME |
|
150 MyLibLibFun3 @ 3 NONAME </codeblock><p>So, as one can observe in the above |
|
151 section where different DEF file entries are created with and without extern |
|
152 "C", the user must make sure that the rule is followed. extern "C" has to |
|
153 be used in both declaration and definition: otherwise the user will either, |
|
154 not be able to build it for all the platforms or, it will not be possible |
|
155 to use those exported C APIs in other applications. </p> </section> |
|
156 </conbody></concept> |