Removed some more dependencies on wine 16-bit specific entities.
[wine.git] / documentation / winelib-bindlls.sgml
blobfaad7a86f7f9a7979b91735996edc921d9d0c999
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 DLL 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, unsigned char f, char g,
66 unsigned char *h);
67 </programlisting>
68 and the linux library exports a corresponding function:
69 <programlisting>
70 signed short MyLinuxFunc (unsigned short a, void *b, void *c,
71 unsigned short *d, void *e, char g, unsigned char *h);
72 </programlisting>
73 </para>
74 </sect1>
76 <sect1 id="bindlls-spec">
77 <title id="bindlls-spec.title">Writing the spec file</title>
78 <para>
79 Start by writing the spec file. This file will describe the interface
80 as if it were a DLL. See elsewhere for the details of the format of
81 a spec file (e.g. man winebuild).
82 </para>
83 <para>
84 In the simple example we want a Wine built-in Dll that corresponds to
85 the MyWin Dll. The spec file is <filename>MyWin.dll.spec</filename> and
86 looks something like this (depending on changes to the way that the
87 specfile is formatted since this was written).
88 <programlisting>
90 # File: MyWin.dll.spec
92 # some sort of copyright
94 # Wine spec file for the MyWin.dll built-in library (a minimal wrapper around the
95 # linux library libMyLinux)
97 # For further details of wine spec files see the Winelib documentation at
98 # www.winehq.com
100 2 stdcall MyWinFunc (long ptr ptr ptr ptr long long ptr) MyProxyWinFunc
102 # End of file
103 </programlisting>
104 Notice that the arguments are flagged as long even though they are
105 smaller than that.
106 Notice also that we do not specify an initial function. With this
107 example we will link directly to the Linux shared library whereas
108 with the ODBC example we will load the Linux shared library dynamically.
109 </para>
110 <para>
111 In the case of the ODBC example you can see this in the file
112 <filename>odbc32.spec</filename>.
113 </para>
114 </sect1>
116 <sect1 id="bindlls-cxx-apis">
117 <title id="bindlls-cxx-apis.title">How to deal with C++ APIs</title>
118 <para>
119 names are mangled, how to demangle them, how to call them
120 </para>
121 </sect1>
123 <sect1 id="bindlls-wrapper">
124 <title id="bindlls-wrapper.title">Writing the wrapper</title>
125 <para>
126 Firstly we will look at the simple example. The main complication of
127 this case is the slightly different argument lists. The f parameter
128 does not have to be passed to the Linux function and the d parameter
129 (theoretically) has to be converted between unsigned long * and
130 unsigned short *. Doing this ensures that the "high" bits of the
131 returned value are set correctly. Also unlike with the ODBC example we
132 will link directly to the Linux Shared Library.
133 <programlisting>
135 * File: MyWin.c
137 * Copyright (c) The copyright holder.
139 * Basic Wine wrapper for the Linux &lt;3rd party library&gt; so that it can be
140 * used by &lt;the application&gt;
142 * Currently this file makes no attempt to be a full wrapper for the &lt;3rd
143 * party library&gt;; it only exports enough for our own use.
145 * Note that this is a Unix file; please don't go converting it to DOS format
146 * (e.g. converting line feeds to Carriage return/Line feed).
148 * This file should be built in a Wine environment as a WineLib library,
149 * linked to the Linux &lt;3rd party&gt; libraries (currently libxxxx.so and
150 * libyyyy.so)
153 #include &lt; &lt;3rd party linux header&gt; &gt;
154 #include &lt;windef.h&gt; /* Part of the Wine header files */
156 signed short WINAPI MyProxyWinFunc (unsigned short a, void *b, void *c,
157 unsigned long *d, void *e, unsigned char f, char g,
158 unsigned char *h)
159 /* This declaration is as defined in the spec file. It is deliberately not
160 * specified in terms of &lt;3rd party&gt; types since we are messing about here
161 * between two operating systems (making it look like a Windows thing when
162 * actually it is a Linux thing). In this way the compiler will point out any
163 * inconsistencies.
164 * For example the fourth argument needs care
167 unsigned short d1;
168 signed short ret;
170 d1 = (unsigned short) *d;
171 ret = &lt;3rd party linux function&gt; (a, b, c, &amp;d1, e, g, h);
172 *d = d1;
174 return ret;
177 /* End of file */
178 </programlisting>
179 </para>
180 <para>
181 For a more extensive case we can use the ODBC example. This is
182 implemented as a header file
183 (<filename class="HeaderFile">proxyodbc.h</filename>) and the actual
184 C source file (<filename>proxyodbc.c</filename>). Although the file
185 is quite long it is extremely simple in structure.
186 </para>
187 <para>
188 <function>DllMain</function> the function is used to initialize the DLL.
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 initialization.
197 </para>
198 </sect1>
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 built-in 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>
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 built-in 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 built-in 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>
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>
304 <!-- Keep this comment at the end of the file
305 Local variables:
306 mode: sgml
307 sgml-parent-document:("winelib-user.sgml" "book" "chapter" "")
308 End: