Git `master` is now FLTK 1.5

23 views
Skip to first unread message

Albrecht Schlosser

unread,
Mar 6, 2025, 12:59:01 PMMar 6
to fltkc...@googlegroups.com
Hi all,

I created Git `branch-1.4` for further maintenance of FLTK 1.4.x and updated the `master` branch to FLTK version 1.5.0.

Except version number updates and removal of autoconf/Makefile's and other "technical" stuff there is only one essential update:
commit dc07f927f1ae97dff76741025856c342794a9662

    Fl_Group: convert array of children to std::vector

    Note: this is only a hidden implementation detail: all concerned
    variables are private, and the code is simplified (less error prone).

    Size of Fl_Group on 64-bit Linux: 168 -> 176 Bytes (+8 Bytes).

    test/group.cxx: test for Fl_Group::{add, insert, remove} etc.

:100644 100644 27c68ef8a f09f98d18 M	FL/Fl_Group.H
:100644 100644 07079cf8c e256e81ec M	src/Fl_Group.cxx
:100644 100644 eff372154 d2e1c9c5f M	test/CMakeLists.txt
:000000 100644 000000000 2e661f560 A	test/group.cxx

This commit *could* be reverted easily if necessary (only FL/Fl_Group.H and src/Fl_Group.cxx; the test program should be kept).

But I really hope that this is not necessary.

Development of FLTK 1.5 can now proceed in git `master` as usual...

As previously with `branch-1.3` backports to FLTK 1.4.x can now be committed/pushed to `branch-1.4`. Please checkout branch-1.4 if you need to do this.

Albrecht

melcher....@googlemail.com

unread,
Mar 6, 2025, 7:26:41 PMMar 6
to fltk.coredev
Thanks very much, Albrecht. I removed most mentions of Fl_String and replaced everything with std::string. This seems to have gone very nicely. This changed a lot of files and would not be easily reversible, but also removes the entire Fl_String implementation (I have not checked how many bytes are saved).

I will add fl_filename_... stuff tomorrow.

Albrecht Schlosser

unread,
Mar 7, 2025, 8:07:06 AMMar 7
to fltkc...@googlegroups.com
On 3/7/25 01:26 Matthias wrote:
> Thanks very much, Albrecht.

Welcome.

> I removed most mentions of Fl_String and replaced everything with
> std::string. This seems to have gone very nicely. This changed a lot
> of files and would not be easily reversible, but also removes the
> entire Fl_String implementation (I have not checked how many bytes are
> saved).

Anyway, I believe we must go forward. Thanks for doing this.

> I will add fl_filename_... stuff tomorrow.

Great, TIA.

Greg Ercolano

unread,
Mar 7, 2025, 12:23:30 PMMar 7
to fltkc...@googlegroups.com
I removed most mentions of Fl_String and replaced everything with
std::string. This seems to have gone very nicely. This changed a lot
of files and would not be easily reversible, but also removes the
entire Fl_String implementation (I have not checked how many bytes are saved).

Anyway, I believe we must go forward. Thanks for doing this.

OK, so for the devs, just curious what are the parameters of use for std going forward in 1.5?

    1. Data use of std elements:
        1a. private only
        1b. private+protected only
        1c. private+protected+public ok
    2. API use of std elements:
        2a. never
        2b. private api only
        2c. private + protected api only
        2d. private+protected+public api ok
    3. Use of #include <std_files> in FLTK library source code:
        3a. in src/*.cxx only
        3b. in src/*.{cxx,H} only
        3c. src/* and FL/* ok
    4. Use of std in test + examples apps:
        4a. never
        4b. ok, with some restrictions
        4c. ok, no restrictions
    5. Other issues/limitations? Example:
       Assuming we don't want to return std::vector thru the public apis, how should we handle returning internal std::vector data of potentially large amounts of data (e.g. Fl_Group::children()):
        5a. Convert to/from C style arrays
        5b. Never convert: continue using C style arrays internally if data must be exposed thru public api
        5c. Use whatever is most efficient: depends on case-by-case basis.

  
I'm guessing currently:

    (1a) private std data only
    (2b) private std api only, no public or protected exposure
    (3b) internal use only, no std stuff in FL/*
    (4c) no restrictions in example code
    (5c) handling of API <-> std up to the developer, no fixed rules

..with possible changes in the future.

Also: should we generally be retooling old C style arrays to std when possible, or is it OK to leave the old C style stuff alone, and retool only when necessary or convenient?

Albrecht Schlosser

unread,
Mar 7, 2025, 1:51:55 PMMar 7
to fltkc...@googlegroups.com
On 3/7/25 18:23 Greg Ercolano wrote:
I removed most mentions of Fl_String and replaced everything with
std::string. This seems to have gone very nicely. This changed a lot
of files and would not be easily reversible, but also removes the
entire Fl_String implementation (I have not checked how many bytes are saved).

Anyway, I believe we must go forward. Thanks for doing this.

OK, so for the devs, just curious what are the parameters of use for std going forward in 1.5?


Some general thoughts:

(A) Currently we should limit internal and API stuff to std::string and std::vector<basic_type> where 'basic_type' is something like int, float, or pointer, for instance <Fl_Widget *> (see Fl_Group).

(B) We can't be too restrictive with the public API because we did already open it for std:: stuff in 1.4.x with a special CMake option: FLTK_OPTION_STD. This option was intended to be used by users and to be always ON starting with 1.5.0. The consequence is that we did already include std:: stuff in the public API, even if it was optional, thus we can't remove it now. Unless we NEED to do that for very important reasons. Removing it would cause a regression for users that use the option in 1.4.x.

(C) It would be almost impossible to "hide" stuff like std::vector and std::string from public headers, even if variables of these types are 'private', for instance the new private `std::vector<Fl_Widget *>child_` in FL/Fl_Group.H. Rationale: if nothing else, then the size of std::vector would change the ABI, and if it is different per compiler, then this is something we will have to live with.

(D) We have already documentation that says "Because of name mangling differences between PC compilers (even between different versions of Visual Studio) you can only use the DLL that is generated with the same compiler version that you built it with". Link: https://www.fltk.org/doc-1.4/intro.html#intro_msvc_dll

This particular documentation is Visual Studio specific but after all reading about compiler ABI's I came to the conclusion that this needs to be extended to other compilers as well. This would not only concern linking to a shared library (.dll, .so) but also static linking - because an object library (.a) has already been pre-compiled with a particular compiler, i.e. the ABI is already established. That's why we (you) started this std-check project which is not obsolete. It should at least find a way to check the compiler version.

The good news: there are obviously wide ranges where compilers are intended to cooperate (e.g. gcc + clang), at least if they use the same libstdc++ (on a particular system). It's hard to tell what happens if you compile a program on one system and try to deploy it to another platform (e.g. Debian Linux <-> Ubuntu <-> Arch <-> others ...).


I'm guessing currently:

    (1a) private std data only
    (2b) private std api only, no public or protected exposure
    (3b) internal use only, no std stuff in FL/*
    (4c) no restrictions in example code
    (5c) handling of API <-> std up to the developer, no fixed rules

..with possible changes in the future.


From a practical point of view I believe that we have to use (allow) this set of parameters:
    1. Data use of std elements:
        1b. private+protected only - with public accessors if useful

    2. API use of std elements:
        2d. private+protected+public api ok

	No direct access to std:: member vars though. We should always use well-defined accessor
        methods so we can change implementation details (see also 1.).

    3. Use of #include <std_files> in FLTK library source code:
        3c. src/* and FL/* ok

	See FL/Fl_Group.H:
          #include <vector>
          std::vector<Fl_Widget *>child_; // vector of children

	For now <vector> and <string> should suffice. IMHO.

    4. Use of std in test + examples apps:
        4c. ok, no restrictions

	Required for testing, obviously.

    5. Other issues/limitations? Example:
       > Assuming we don't want to return std::vector thru the public apis, how should
       > we handle returning internal std::vector data of potentially large amounts of
       > data (e.g. Fl_Group::children()):

        5a. Convert to/from C style arrays where possible and useful
        5c. Use whatever is most efficient: depends on case-by-case basis.

	5a) Example Fl_Group::array() which is *unchanged* WRT 1.4.x and earlier.
	https://www.fltk.org/doc-1.4/classFl__Group.html#ab5a03e490bb0dc19f8da7e3e4acdca17
	The new implementation is to return a pointer to the data() array of the vector.

        5c) I believe that we should allow the user to provide input parameters, e.g.
	std::string and std::vector for some selected parameters. Currently not strictly
	necessary, but can be added in the future.

	5c) Some API's that return strings like fl_input() and other "common dialogs"
	*really* need to return strings as std::string to the user program to avoid
	facts like this:
	"Returns the string in an internally allocated buffer that may be changed later.
	 You must copy the string immediately after return from this method - at least
	 before the next execution of the event loop."
	The new method fl_input_str() exists already (it was added in 1.4.x as option)
	but is not yet documented.
	I'm not sure if it is already *active*, or if it is disabled by compiler guards.

	My vote is (5a) where possible and (5c) where necessary.

Also: should we generally be retooling old C style arrays to std when possible, or is it OK to leave the old C style stuff alone, and retool only when necessary or convenient?


I'd say the latter, but when is it "necessary" and when is it "convenient" ?

I tend to retool everything where we "invented" our own classes because we couldn't use std::string or std::vector. Such code is error-prone and makes the library larger than necessary. Therefore it should be replaced with std:: stuff.

Wherever we use standard C-style arrays we don't really need to change anything, but it could be done whenever the code is changed anyway or to fix bugs.

Reply all
Reply to author
Forward
0 new messages