Fixed a few function pointer typedefs.
[wine] / documentation / winelib-bindlls.sgml
1   <chapter id="bindlls">
2     <title id="bindlls.title">Using Linux libraries as dlls</title>
3     <sect1 id="bindlls-intro">
4       <title id="binary-dlls-intro.title">Introduction</title>
5       <para>
6         For one reason or another you may find yourself with a Linux shared
7         library that you want to use as if it were a Windows Dll.  There are
8         various reasons for this including the following:
9         <itemizedlist>
10           <listitem>
11             <para>
12               You are porting a large application that uses several third-party
13               libraries.  One is available on Linux but you are not yet ready
14               to link to it directly as a Linux shared library.
15             </para>
16           </listitem>
17           <listitem>
18             <para>
19               There is a well-defined interface available and there are several 
20               Linux solutions that are available for it. 
21               (The ODBC interface in Wine)
22             </para>
23           </listitem>
24           <listitem>
25             <para>
26               You wish to do something that you can do in Linux but Wine does
27               not yet support it.
28             </para>
29           </listitem>
30         </itemizedlist>
31       </para>
32       <para>
33         The process for dealing with these situations is actually quite simple.
34         You need to write a spec file that will describe the library's 
35         interface in the same format as a Dll (primarily what functions it
36         exports).  Also you will want to write a small wrapper around the
37         library.  You combine these to form a Wine builtin Dll that links to the
38         Linux library.  Then you modify the Dll Overrides in the wine config
39         file to ensure that this new builtin dll is called rather than any
40         windows version.
41       </para>
42       <para>
43         In this section we will look at two examples.  The first example is
44         extremely simple and leads into the subject in "baby steps".  The
45         second example is the ODBC interface proxy in Wine.  The files to which
46         we will refer for the ODBC example are currently in the 
47         <filename class="Directory">dlls/odbc32</filename> directory of the
48         Wine source.
49       </para>
50       <para>
51          The first example is based very closely on a real case (the names
52          of the functions etc. have been changed to protect the innocent).
53          A large Windows application includes a DLL that links to a third-party
54          DLL.  For various reasons the third-party DLL does not work too well
55          under Wine.  However the third-party DLL is also available for the
56          Linux environment.  Conveniently the DLL and Linux shared library 
57          export only a small number of functions and the application only uses
58          one of those.
59        </para>
60        <para>
61          Specifically, the application calls a function:
62 <programlisting>
63 signed short WINAPI MyWinFunc (unsigned short a, void *b, void *c,
64         unsigned long *d, void *e, unsigned char f, char g,
65         unsigned char *h);
66 </programlisting>
67          and the linux library exports a corresponding function:
68 <programlisting>
69 signed short MyLinuxFunc (unsigned short a, void *b, void *c,
70         unsigned short *d, void *e, char g, unsigned char *h);
71 </programlisting>
72        </para>
73     </sect1>
74
75     <sect1 id="bindlls-spec">
76       <title id="bindlls-spec.title">Writing the spec file</title>
77       <para>
78         Start by writing the spec file.  This file will describe the interface
79         as if it were a dll.  See elsewhere for the details of the format of
80         a spec file (e.g. man winebuild).
81       </para>
82       <para>
83         In the simple example we want a Wine builtin Dll that corresponds to
84         the MyWin Dll.  The spec file is <filename>MyWin.dll.spec</filename> and
85         looks something like this (depending on changes to the way that the
86         specfile is formatted since this was written).
87 <programlisting>
88 #
89 # File: MyWin.dll.spec
90 #
91 # some sort of copyright
92 #
93 # Wine spec file for the MyWin.dll builtin library (a minimal wrapper around the
94 # linux library libMyLinux)
95 #
96 # For further details of wine spec files see the Winelib documentation at
97 # www.winehq.com
98
99 2 stdcall MyWinFunc (long ptr ptr ptr ptr long long ptr) MyProxyWinFunc
100
101 # End of file
102 </programlisting>
103         Notice that the arguments are flagged as long even though they are
104         smaller than that.
105         Notice also that we do not specify an initial function.  With this
106         example we will link directly to the Linux shared library whereas 
107         with the ODBC example we will load the Linux shared library dynamically.
108       </para>
109       <para>
110         In the case of the ODBC example you can see this in the file 
111         <filename>odbc32.spec</filename>.
112       </para>
113     </sect1>
114
115     <sect1 id="bindlls-cxx-apis">
116       <title id="bindlls-cxx-apis.title">How to deal with C++ APIs</title>
117       <para>
118         names are mangled, how to demangle them, how to call them
119       </para>
120     </sect1>
121
122     <sect1 id="bindlls-wrapper">
123       <title id="bindlls-wrapper.title">Writing the wrapper</title>
124       <para>
125         Firstly we will look at the simple example.  The main complication of
126         this case is the slightly different argument lists.  The f parameter
127         does not have to be passed to the Linux function and the d parameter
128         (theoretically) has to be converted between unsigned long * and
129         unsigned short *.  Doing this ensures that the "high" bits of the
130         returned value are set correctly.  Also unlike with the ODBC example we
131         will link directly to the Linux Shared Library.
132         <programlisting>
133 /*
134  * File: MyWin.c
135  *
136  * Copyright (c) The copyright holder.
137  *
138  * Basic Wine wrapper for the Linux &lt;3rd party library&gt; so that it can be
139  * used by &lt;the application&gt;
140  *
141  * Currently this file makes no attempt to be a full wrapper for the &lt;3rd
142  * party library&gt;; it only exports enough for our own use.
143  *
144  * Note that this is a Unix file; please don't go converting it to DOS format
145  * (e.g. converting line feeds to Carriage return/Line feed).
146  *
147  * This file should be built in a Wine environment as a WineLib library, 
148  * linked to the Linux &lt;3rd party&gt; libraries (currently libxxxx.so and 
149  * libyyyy.so)
150  */
151
152 #include &lt; &lt;3rd party linux header&gt; &gt;
153 #include &lt;windef.h&gt; /* Part of the Wine header files */
154
155 signed short WINAPI MyProxyWinFunc (unsigned short a, void *b, void *c,
156                 unsigned long *d, void *e, unsigned char f, char g, 
157                 unsigned char *h)
158 /* This declaration is as defined in the spec file.  It is deliberately not
159  * specified in terms of &lt;3rd party&gt; types since we are messing about here
160  * between two operating systems (making it look like a Windows thing when
161  * actually it is a Linux thing).  In this way the compiler will point out any
162  * inconsistencies.
163  * For example the fourth argument needs care
164  */
165 {
166     unsigned short d1;
167     signed short ret;
168
169     d1 = (unsigned short) *d;
170     ret = &lt;3rd party linux function&gt; (a, b, c, &amp;d1, e, g, h);
171     *d = d1;
172
173     return ret;
174 }
175
176 /* End of file */
177         </programlisting>
178       </para>
179       <para>
180         For a more extensive case we can use the ODBC example.  This is
181         implemented as a header file 
182         (<filename class="HeaderFile">proxyodbc.h</filename>) and the actual
183         C source file (<filename>proxyodbc.c</filename>).  Although the file
184         is quite long it is extremely simple in structure.
185       </para>
186       <para>
187         The MAIN_OdbcInit function is the function that was named in the
188         <link linkend="bindlls-spec">spec file</link> as the init function.
189         On the process attach event the function dynamically links to the
190         desired Linux ODBC library (since there are several available) and
191         builds a list of function pointers.  It unlinks on the process
192         detach event.
193       </para>
194       <para>
195         Then each of the functions simply calls the appropriate Linux function
196         through the function pointer that was set up during initialisation.
197       </para>
198     </sect1>
199
200     <sect1 id="bindlls-building">
201       <title id="binary-dlls-building.title">Building</title>
202       <para>
203         So how do we actually build the Wine builtin Dll?  The easiest way is
204         to get Winemaker to do the hard work for us.  For the simple example we
205         have two source files (the wrapper and the spec file).  We also have
206         the 3rd party header and library files of course.
207       </para>
208       <para>
209         Put the two source files in a suitable directory and then use 
210         winemaker to create the build framework, including configure script,
211         makefile etc.  You will want to use the following options of 
212         winemaker:
213         <itemizedlist>
214           <listitem>
215             <para>
216               --nosource-fix and --nogenerate-specs (requires winemaker version
217               0.5.8 or later) to ensure that the two files are not modified.
218               (If using an older version of winemaker then make the two files
219               readonly and ignore the complaints about being unable to modify
220               them).
221             </para>
222           </listitem>
223           <listitem>
224             <para>
225               --dll --single-target MyWin --nomfc to specify the target
226             </para>
227           </listitem>
228           <listitem>
229             <para>
230               -DMightNeedSomething -I3rd_party_include -L3rd_party_lib -lxxxx
231               -lyyyy where these are the locations of the header files etc.
232             </para>
233           </listitem>
234         </itemizedlist>
235       </para>
236       <para>
237         After running winemaker I like to edit the Makefile.in to add the line
238         CEXTRA = -Wall just before the DEFINES =.
239       </para>
240       <para>
241         Then simply run the configure and make as normal (described elsewhere).
242       </para>
243     </sect1>
244
245     <sect1 id="bindlls-installing">
246       <title id="binary-dlls-installing.title">Installing</title>
247       <para>
248         So how do you install the proxy and ensure that everything connects up
249         correctly?  You have quite a bit of flexibility in this area so what 
250         follows are not the only options available.
251       </para>
252       <para>
253         Ensure that the actual Linux Shared Object is placed somewhere where
254         the Linux system will be able to find it.  Typically this means it 
255         should be in one of the directories mentioned in the /etc/ld.so.conf
256         file or somewhere in the path specified by LD_LIBRARY_PATH.  If you 
257         can link to it from a Linux program it should be OK.
258       </para>
259       <para>
260         Put the proxy shared object (MyWin.dll.so) in the same place as the
261         rest of the builtin dlls.  (If you used winemaker to set up your build
262         environment then running "make install" as root should do that for you)
263         Alternatively ensure that WINEDLLPATH includes the directory containing
264         the proxy shared object.
265       </para>
266       <para>
267         If you have both a Windows dll and a Linux Dll/proxy pair then you will
268         have to ensure that the correct one gets called.  The easiest way is
269         probably simply to rename the windows version so that it doesn't get
270         detected.  Alternatively you could specify in the DllOverrides section
271         (or the AppDefaults\\myprog.exe\\DllOverrides section) of the config
272         file (in your .wine directory) that the builtin version be used.  Note
273         that if the Windows version Dll is present and is in the same
274         directory as the executable (as opposed to being in the Windows
275         directory) then you will currently need to specify the whole path to
276         the dll, not merely its name.
277       </para>
278       <para>
279         Once you have done this you should be using the Linux Shared Object
280         successfully.  If you have problems then use the --debugmsg +module
281         options to wine to see what is actually happening.
282       </para>
283     </sect1>
284
285     <sect1 id="bindlls-advanced">
286       <title id="binary-dlls-advanced.title">Advanced options</title>
287       <para>
288         Here are a few more advanced options.
289       </para>
290       <sect2 id="bindlls-adv-filenames">
291         <title id="binary-dlls-adv-filenames.title">Converting filenames</title>
292         <para>
293           Suppose you want to convert incoming DOS format filenames to their
294           Unix equivalent.  Of course there is no suitable function in the true
295           Microsoft Windows API, but wine provides a function for just this
296           task and exports it from its copy of the kernel32 dll.  The function
297           is wine_get_unix_file_name (defined in winbase.h).  Use the -ikernel32
298           option to winemaker to link to it.
299         </para>
300       </sect2>
301     </sect1>
302   </chapter>
303
304 <!-- Keep this comment at the end of the file
305 Local variables:
306 mode: sgml
307 sgml-parent-document:("wine-doc.sgml" "book" "chapter" "")
308 End:
309 -->