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