Ian MacArthur wrote:
> 
> I suspect the "best" option here is possibly to revert the function prototype 
> to the non-const version...?
> 
> I mean, change the typedef for Fl_File_Sort_F back to being non-const... 
> Would that do the trick, I wonder.

I have tried the intermediate solution too, but this don't work at all.
Either all parameters must be const, or all non-const. Otherwise the
strict C++ type checking breaks anything.

I have found this article about C++ ABI issues:
http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++
If I understand it correctly, we can't add an overload to
'fl_filename_list()' because this is only allowed if the function is
already overloaded (what is not the case here).

I think there is no elegant way to do it. The next best solution is IMHO
to add both variants and let the preprocessor select one via
'FLTK_ABI_VERSION'. This way sometimes in the future things will
converge with POSIX (but in the meantime it still looks ugly).

This patch:
http://micha.freeshell.org/tmp/str_2931_r9827_v3.patch
do the following things:
----------------------------------------------------------------------
- Add both API variants (const and non-const) to 'FL/filenam.H'.
  'fl_filename_list()' is still declared as C++ because I'm not sure
  whether changing it to C may have other unwanted side effects on the
  file chooser stuff that use it.

- The complete OS wrapping for 'scandir()' is moved to 'src/scandir.c'
  Reason: The v2 patch has revealed, that a C function pointer cast
  in a C++ file don't work as needed. The result in actuality is a
  pointer to a C++ function. Passing such a pointer to a C function
  may rely on undefined behaviour of the compiler (by assuming the two
  pointer types use the same memory representation).
  The wrapper 'fl_scandir_old()' do the cast to non-const for the old
  ABI using the C compiler and can be removed after the ABI switch.
  A new header 'src/scandir.h' is added.

- The file 'src/filename_list.cxx' now calls 'fl_scandir_old()' or
  'fl_scandir()' for the new ABI. Now it do always the same for all
  OS (except Windows).
  All compare functions for sorting are now defined here so that the
  ABI switching can be pushed out of 'src/numericsort.c'.

- The file 'src/numericsort.c' now only implements the low level
  functionality required for numeric sorting using the same wrapper
  technique as 'src/scandir.c' that can be removed after the ABI
  change.
  The low level function is no longer declared 'static'. To avoid a
  name collision if 'FLTK_1_0_COMPAT' is defined, the low level
  function is renamed (compare with the end of 'FL/filename.H').
  A new header 'src/numericsort.h' is added.
----------------------------------------------------------------------

Why not do the ABI switching in the C files?
Because 'FL/Enumerations.H' and 'FL/filename.H' claim to be C++ header
files (by the capital H in the extension). Therefore they should only
be included in C++ files.

The bits are cleaner assigned now: The scandir() stuff is done in
scandir.c and the rest (UTF-8 name mangling and the like) that has
nothing to do with the low level C implementation is done in the FLTK
C++ wrapper fl_filename_list().

GCC and the Sun compiler now show no warnings anymore for the files
this patch relates to.

And finally:
I have verified that the old ABI is still 1.3.0 compatible using the
approach with the shared libraries mentioned by Albrecht. The test
program looks like this:
----------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include "filename.H"

/* Test 'fl_filename_list()' implementation */
int main(int argc, char **argv)
{
  int res, i;
  struct dirent **namelist;

  printf("Test fl_filename_list() in current working dir ...\n");
  res = fl_filename_list(".", &namelist, fl_numericsort);
  printf("Result: %d entries \n", res);

  printf("----------------------------------------"
         "----------------------------------------\n");
  for (i = 0; i < res; ++i)
  {
    printf("%d: %s\n", i, namelist[i]->d_name);
  }
  printf("----------------------------------------"
         "----------------------------------------\n");

  if (-1 != res)  { res = 0; }
  exit(res);
}
----------------------------------------------------------------------

It works now as long as 'FLTK_ABI_VERSION' is not defined. An
application build for a shared 1.3.0 library can still use the new
version.


Regards,

Micha
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to