177 lines
6.0 KiB
Plaintext
177 lines
6.0 KiB
Plaintext
|
Binary Compatability and wxWidgets
|
||
|
==================================
|
||
|
0. Purpose
|
||
|
----------
|
||
|
|
||
|
This is broad technote covering all aspects of binary compatability with
|
||
|
wxWidgets.
|
||
|
|
||
|
1. Releases
|
||
|
-----------
|
||
|
|
||
|
General overview of releases can be found in tn0012.txt, but for
|
||
|
completeness the wxWidgets release version number is as follows:
|
||
|
|
||
|
2.6.2
|
||
|
|
||
|
Where
|
||
|
|
||
|
2 6 2
|
||
|
Major Minor Release
|
||
|
|
||
|
(I.E. Major.Minor.Release).
|
||
|
|
||
|
All Release versions where the Minor is EVEN (2.4.x,2.6.x
|
||
|
etc. ODD minors are development versions) are expected to be binary
|
||
|
compatable. Note that this means FORWARD binary compatability only -
|
||
|
new methods to classes are ok as long as they arn't virtual, etc.
|
||
|
|
||
|
2. What kind of changes are NOT binary compatable
|
||
|
-------------------------------------------------
|
||
|
|
||
|
If its still up, the KDE guide is a good reference:
|
||
|
http://developer.kde.org/documentation/other/binarycompatibility.html
|
||
|
|
||
|
The changes that are NOT binary compatable:
|
||
|
- Adding a virtual function
|
||
|
- Changing the name of a any function or variable
|
||
|
- Changing the signature of a virtual function (adding a parameter,
|
||
|
even a default one)
|
||
|
- Changing the order of the virtual functions in a class
|
||
|
["switching" them, etc.]
|
||
|
- Changing access privalages to a function (protected to private etc.)
|
||
|
[unlike KDE we need to support windows so this is not allowed]
|
||
|
- Adding a member variable
|
||
|
- Changing the order of non-static member variables
|
||
|
|
||
|
|
||
|
3. wxABI_VERSION and BACKWARD binary compatability
|
||
|
--------------------------------------------------
|
||
|
|
||
|
As mentioned we do not support BACKWARD binary compatability.
|
||
|
|
||
|
However, for this purpose we have the macro wxABI_VERSION. All
|
||
|
new symbols added to binary compatable releases are to be ifed
|
||
|
with wxABI_VERSION.
|
||
|
|
||
|
The layout of wxABI_VERSION is as follows:
|
||
|
|
||
|
20602
|
||
|
|
||
|
where
|
||
|
|
||
|
20 60 2
|
||
|
Major Minor Release
|
||
|
|
||
|
I.E. it corresponds to the wxWidgets release in {1}.
|
||
|
|
||
|
An example of using wxABI_VERSION is as follows for symbols
|
||
|
only in a 2.6.2 release:
|
||
|
|
||
|
#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
|
||
|
bool Load(const wxURI& location, const wxURI& proxy);
|
||
|
|
||
|
wxFileOffset GetDownloadProgress();
|
||
|
wxFileOffset GetDownloadTotal();
|
||
|
|
||
|
bool ShowPlayerControls(
|
||
|
wxMediaCtrlPlayerControls flags =
|
||
|
wxMEDIACTRLPLAYERCONTROLS_DEFAULT);
|
||
|
|
||
|
//helpers for the wxPython people
|
||
|
bool LoadURI(const wxString& fileName)
|
||
|
{ return Load(wxURI(fileName)); }
|
||
|
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
|
||
|
{ return Load(wxURI(fileName), wxURI(proxy)); }
|
||
|
#endif
|
||
|
|
||
|
|
||
|
4. Workarounds for adding virtual functions
|
||
|
-------------------------------------------
|
||
|
|
||
|
Originally the idea for adding virtual functions to binary compatable
|
||
|
releases was to pad out some empty "reserved" functions and then
|
||
|
rename those later when someone needed to add a virtual function.
|
||
|
|
||
|
However, after there was some actual testing of the idea a lot of
|
||
|
controversy erupted. Eventually we decided against the idea, and
|
||
|
instead devised a new method for doing so called wxShadowObject.
|
||
|
|
||
|
wxShadowObject is a class derived from wxObject that provides a means
|
||
|
of adding functions and/or member variables to a class internally
|
||
|
to wxWidgets. It does so by storing these in a hash map inside of
|
||
|
it, looking it up when the function etc. is called. wxShadowObject
|
||
|
is generally stored inside a reserved member variable.
|
||
|
|
||
|
wxShadowObject resides in include/wx/clntdata.h.
|
||
|
|
||
|
To use wxShadowObject, you first call AddMethod or AddField with
|
||
|
the first parameter being the name of the field and/or method
|
||
|
you want, and the second parameter being the value of the
|
||
|
field and/or method.
|
||
|
|
||
|
In the case of fields this is a void*, and in the case of method
|
||
|
is a wxShadowObjectMethod which is a typedef:
|
||
|
typedef int (*wxShadowObjectMethod)(void*, void*);
|
||
|
|
||
|
After you add a field, you can set it via SetField with the same
|
||
|
params as AddField, the second param being the value to set
|
||
|
the field to. You can get the field after you call AddField
|
||
|
via GetField, with the parameters as the other two field functions,
|
||
|
only in the case the second parameter is the fallback
|
||
|
value for the field in the case of it not being found in the
|
||
|
hash map.
|
||
|
|
||
|
You can call a method after you add it via InvokeMethod, which
|
||
|
returns a bool indicating whether or not the method was found
|
||
|
in the hash map, and has 4 parameters. The first parameter is
|
||
|
the name of the method you wish to call, the second is the first
|
||
|
parameter passed to the wxShadowObjectMethod, the third is the
|
||
|
second parameter passed to that wxShadowObjectMethod, and the
|
||
|
fourth is the return value of the wxShadowObjectMethod.
|
||
|
|
||
|
5. version-script.in
|
||
|
--------------------
|
||
|
|
||
|
For ld/libtool we use sun-style version scripts. Basically
|
||
|
anything which fits the conditions of being ifed via wxABI_VERSION
|
||
|
needs to go here also.
|
||
|
|
||
|
The file has the layout as follows:
|
||
|
|
||
|
@WX_VERSION_TAG@.X
|
||
|
|
||
|
Where X is the current Release as mentioned earlier, i.e. 2. This
|
||
|
is following by an opening bracket "{", followed by "global:",
|
||
|
followed by the added symbols, then followed by "}", and then
|
||
|
the file is either followed by earlier Releases or ended by
|
||
|
a @WX_VERSION_TAG@ block without the period or Release.
|
||
|
|
||
|
Added symbols have the form
|
||
|
*CLASSNAME*METHODNAME*PARAM1*PARAM2*...
|
||
|
|
||
|
Where CLASSNAME is the name of the class or blank (along with
|
||
|
omitted *) in the case of a global function. METHODNAME is the name
|
||
|
of the class method or global function. This is followed by another
|
||
|
star "*" and then the type of each subsequent parameter for the function,
|
||
|
such as *wxString etc..
|
||
|
|
||
|
6. Testing binary compatability between releases
|
||
|
------------------------------------------------
|
||
|
|
||
|
An easy way of testing binary compatability is just to build wxWidgets
|
||
|
in dll/dynamic library mode and then switch out the current library
|
||
|
in question with an earlier stable version of the library, then running
|
||
|
the application in question again. If it runs OK then there is usually
|
||
|
binary compatability between those releases.
|
||
|
|
||
|
You can also break into your debugger or whatever program you want
|
||
|
to use and check the memory layout of the class. If it is the same
|
||
|
then it is binary compatable.
|
||
|
|
||
|
|
||
|
=== EOF ===
|
||
|
|
||
|
Author: RN
|
||
|
Version: $Id$
|