This sounds like a very interesting approach, IOhannes. Regarding disk space it is nowadays no problem at all to store fat binaries, even on a small device like Raspberry Pi.
To be sure if I understand the idea correctly: the setup method of each class is renamed (by the build system, essentially), and precision-aware Pd looks for that new name so it loads the code for the proper precision. This way you can bundle two versions of a class (or lib) in a single executable, one for each precision. The setup method of the wrong precision will not be called by Pd. Am I right?
Does it also mean the rest of the wrong-precision code will not be loaded? What will happen with unintentionally exported symbols, like private functions accidentally not declared static, or functions defined in shared files? Compiler-dependent methods exist to hide symbols by default. Then, the same approach for renaming class setup methods according to precision, might be used to explicitly define them as exported symbol.
What would a legacy Pd build do with fat-precision binaries? Could we consider single precision the default and not rename the setup function compiled for single precision so it will still work with legacy Pd? If the extensions are not modified, a user can't see whether an external is fat-precision or not.
Katja
On Wed, Feb 4, 2015 at 3:40 AM, IOhannes m zmölnig zmoelnig@iem.at wrote:
On 02/03/2015 08:29 PM, IOhannes m zmölnig wrote:
On 02/03/2015 08:16 PM, IOhannes m zmölnig wrote:
EXTERN t_class *class_new32(...) EXTERN t_class *class_new64(...)
this btw, would also allow to write externals that provide both single- and double-prevision versions of an objectclass, without the need to change the extension.
they key to this is to provide dummy registration classes for the unsupported precisions, so an external compiled for the "wrong" architecture can be loaded by dlopen() but cannot actually *do* anything (wrong).
it's probably possible to all this in a single wrapper file, but i hope it's easier to understand without preprocessor magic.
a probably more readable example is the following: suppose we have a implementation of a given external (whose author used t_float/t_sample throughout, but has not done anything yet to port it to a singe/double "phat" binary. the objectclass is "mycobject" and lives in mycobject.c
then the following should be enough to make a phat binary: <mycobject_phat.c> void mycobject_setup32(); void mycobject_setup64(); void mycobject_setup() { mycobject_setup64(); mycobject_setup32(); } <mycobject_phat.c>
and compile the original code with the above glue as follows: $ cc -c -o mycobject-single.o mycobject.c -DPD_FLOATSIZE=32 \ -Dmycobject_setup=mycobject_setup32 $ cc -c -o mycobject-double.o mycobject.c -DPD_FLOATSIZE=64 \ -Dmycobject_setup=mycobject_setup64 $ cc -c -o mycobject-phat.o mycobject-phat.c $ cc -o mycobject.pd_linux \ mycobject-single.o mycobject-double.o mycobject-phat.o -lc
so the changes required to build such phat binaries are mainly (only¹) in the build-system, and no (properly written) code needs be touched.
gfmadsr IOhannes
¹ the glue-code given above is trivial and it should be easy to write a reuseable wrapper that is part of the build-system. something like embedding the following file in the build-system <phat.c> #define CONCAT_EXPAND(s1, s2) s1 ## s2 #define CONCAT(s1,s2) CONCAT_EXPAND(s1,s2) void CONCAT(SETUP, 32); void CONCAT(SETUP, 64); void SETUP () { CONCAT(SETUP, 32); CONCAT(SETUP, 64); return 0; } </phat.c> and compiling it as (3rd line in the above example): $ cc -c -o mycobject-phat.o phat.c -DSETUP=mycobject_setup
Pd-dev mailing list Pd-dev@lists.iem.at http://lists.puredata.info/listinfo/pd-dev