Big trouble with a max object I made: addftx not working properly on Windows, working perfectly on O


    Mar 14 2006 | 2:11 pm
    Hello,
    I have an object with 5 inlets. In new, I'm doing: floatin(x,4); intin(x,3); intin(x,2); intin(x,1);
    in main, I'm doing: addint((method)testobj_int); addinx((method)testobj_in1, 1); addinx((method)testobj_in2, 2); addinx((method)testobj_in3, 3); addftx((method)testobj_ft4, 4);
    This object just post out the value received from the inlet. It's working perfectly on Mac. On Windows, the float inlet is receiving random big big values.
    I don't know what's wrong? - my code - my VCPROJ options - my maxmsp sdk install - anything else (problem is not in %f, because before being empty, my object was sending values to an outlet, and the value sent was also wrong).
    Attached, mxo for OSX, mxe for XP, source and win project.
    Best regards and thanks for your help, Chris
    NB: (maxmsp 457)
    Results of the patch on windows: sending an int gives: ft4=0.000000 in3=11 in2=11 in1=11 sending a float gives : ft4=-36893488147419103000.000000 in3=0 in2=0 in1=0
    The patch is:
    #include "ext.h"
    typedef struct testobj { Object x_ob; } t_testobj;
    void *testobj_class;
    void testobj_int(t_testobj *x, long n); void testobj_in1(t_testobj *x, long n); void testobj_in2(t_testobj *x, long n); void testobj_in3(t_testobj *x, long n);
    void testobj_ft4(t_testobj *x, float g);
    void *testobj_new(Symbol *s);
    void main(void) { setup((t_messlist **)&testobj_class, (method)testobj_new, 0L, (short)sizeof(t_testobj), 0L, 0);
    addint((method)testobj_int); addinx((method)testobj_in1, 1); addinx((method)testobj_in2, 2); addinx((method)testobj_in3, 3);
    addftx((method)testobj_ft4, 4); }
    void testobj_int(t_testobj *x, long n) { post("int=%d",n); } void testobj_in1(t_testobj *x, long n) { post("in1=%d",n); } void testobj_in2(t_testobj *x, long n) { post("in2=%d",n); } void testobj_in3(t_testobj *x, long n) { post("in3=%d",n); } void testobj_ft4(t_testobj *x, float g) { post("ft4=%f",g); }
    void *testobj_new(Symbol *s) { t_testobj *x = (t_testobj *)newobject(testobj_class);
    floatin(x,4); intin(x,3); intin(x,2); intin(x,1);
    return(x); }

    • Mar 14 2006 | 2:15 pm
      On Windows, arguments using float values must be doubles.
      jb
    • Mar 14 2006 | 2:17 pm
      Hi Chris, as far as i know (although being biased by PureData), float handlers take double arguments, like in void testobj_ft4(t_testobj *x, double g);
      greetings, Thomas
      -- Thomas Grill http://grrrr.org
    • Mar 14 2006 | 2:25 pm
      not sure, but I remember functions which interface with max need to use double instead of float. Try this:
      void testobj_ft4(t_testobj *x, double g); void testobj_ft4(t_testobj *x, double g) { post("ft4=%f",g); }
      hth, t_
    • Mar 14 2006 | 2:27 pm
      I need to type faster, 3rd place damn it ;-)
      t_
    • Mar 14 2006 | 2:29 pm
      Thijs Koerselman schrieb: > not sure, but I remember functions which interface with max need to > use double instead of float. Try this: > > void testobj_ft4(t_testobj *x, double g); > void testobj_ft4(t_testobj *x, double g) { post("ft4=%f",g); } it's void testobj_ft4(t_testobj *x, double g) { post("ft4=%lf",g); }
      greetings, Thomas
      -- Thomas Grill http://grrrr.org
    • Mar 14 2006 | 2:36 pm
    • Mar 14 2006 | 2:42 pm
      Yes, go ahead and use double for both.
      jb
    • Mar 14 2006 | 2:49 pm
      On 14-Mar-2006, at 15:27, Thijs Koerselman wrote:
      > I need to type faster, 3rd place damn it ;-)
      And I need to read faster, I don't even rate an honorable mention this time %-}
      The float/double thing is up there in the top 3 max-dev FAQs. And it is, admittedly, a little weird that all Mac compilers nowadays default to double-precision when they see float in a function prototype while Windows compilers (universally?) insist on single- precision.
      Given that there's no list FAQ, it would be, imho, a Good Idea(tm) if the SDK uniformly used explicit double in all sample code. I can understand if this is not the absolute highest priority at C74.
      My highest priorities are cool new stuff for Litter Power and iCE, so I'll get back to work (and miss the next opportunity to be a hero for a minute).
      -- P.
      -------------- http://www.bek.no/~pcastine/Litter/ ------------- Peter Castine | +--> Litter Power & Litter Bundle for Jitter |.................................................... p@castine.de | iCE: Sequencing, Recording, and Interface Building pcastine@gmx.net | for Max/MSP pcastine@bek.no | http://www.dspaudio.com/ Extremely cool 4-15@kagi.com |.................................................... | home|chez nous|wir|i nostri http://www.castine.de/
    • Mar 14 2006 | 3:02 pm
      > The float/double thing is up there in the top 3 max-dev FAQs. And it is, > admittedly, a little weird that all Mac compilers nowadays default to > double-precision when they see float in a function prototype while
      I don't understand... calling this code in my objects void myfunc(float f); void test() { post("sizeof(float)=%d sizeof(double)=%dn",sizeof(float),sizeof(double)); myfunc(1.0f); } void myfunc(float f) { post("sizeof(f)=%dn",sizeof(f)); }
      gives as result:
      sizeof(float)=4 sizeof(double)=8 sizeof(f)=4
    • Mar 14 2006 | 6:27 pm
      I"m not quite sure what your code is telling us and I am not convinced it is telling us what you think it's telling us (or what I think you think it thinks it's telling us). Looking at the disassembled code may be instructive and not a little surprising (see below).
      In any case, Max passes de-atomized floats as 64-bit IEEE-754 double- precision values to your functions. That's the Max API, like it or love it.
      On Windows you *must* declare floating-point parameters as doubles in function prototypes & definitions, otherwise your code is tanked.
      On Mac OS you *may* declare floating-point parameters as doubles. (Incidentally, in the early days of Mac OS PPC Max development it was also mandatory to declare those parameters as doubles.)
      For cross-platform compatibility, the simplest, most straight-forward solution is to always use double in your callbacks.
      On 14-Mar-2006, at 16:02, Chris wrote:
      > I don't understand... > calling this code in my objects > void myfunc(float f); > void test() > { > post("sizeof(float)=%d sizeof(double)=%dn",sizeof > (float),sizeof(double)); > myfunc(1.0f);
      The call to myfunc(), on CW (w/PPC Carbon Target), generates a lwz instruction to pass 1.0f. Which means your carefully specified single- precision is loaded into a 64-bit register, complete with conversion to double-precision. Go figure.
      > } > void myfunc(float f) > { > post("sizeof(f)=%dn",sizeof(f));
      While we're here and being anal-retentive, you would be universally safer to use a %ld or %lu specifier in your format string, since sizeof() returns an unsigned long, which is not necessarily the same size as an int. Granted, nowadays int is pretty much always 32-bit, but that's not what the ANSI C spec says.
      > } > > > gives as result: > > sizeof(float)=4 sizeof(double)=8 > sizeof(f)=4
      -------------- http://www.bek.no/~pcastine/Litter/ ------------- Peter Castine | +--> Litter Power & Litter Bundle for Jitter |.................................................... p@castine.de | iCE: Sequencing, Recording, and Interface Building pcastine@gmx.net | for Max/MSP pcastine@bek.no | http://www.dspaudio.com/ Extremely cool 4-15@kagi.com |.................................................... | home|chez nous|wir|i nostri http://www.castine.de/
    • Mar 14 2006 | 6:49 pm
      > I"m not quite sure what your code is telling us and I am not convinced > it is telling us what you think it's telling us (or what I think you > think it thinks it's telling us). Looking at the disassembled code may > be instructive and not a little surprising (see below). the code was just to show that I didn't understand where 32b float was transformed as 64b double.
      > In any case, Max passes de-atomized floats as 64-bit IEEE-754 > double-precision values to your functions. That's the Max API, like it > or love it. OK...
      > On Windows you *must* declare floating-point parameters as doubles in
      > On Mac OS you *may* declare floating-point parameters as doubles.
      > For cross-platform compatibility, the simplest, most straight-forward > solution is to always use double in your callbacks.
      I just changed all my max object callbacks using float to double. That's a good advide. The SDK doc should be changed to remove all float from examples.
      Best regards, Chris
    • Mar 16 2006 | 5:44 pm
      Hi,
      I just remarked than outlet(x,double x) doesn't exists on windows (nor on mac), we have to use outlet(x,float x)
      this is not very logical. We are obliged to use double when the real number comes from an inlet, but for outlet, we have to use float...
      Regards Chris
    • Mar 16 2006 | 7:55 pm
      On Mar 16, 2006, at 9:44 AM, Chris wrote:
      > I just remarked than outlet(x,double x) > doesn't exists on windows (nor on mac), we have to use outlet > (x,float x) > > this is not very logical. We are obliged to use double when the > real number comes from an inlet, but for outlet, we have to use > float...
      Basically these are two different things. One is has to do with a function pointer (not known at compile time as far as Max is concerned) which is dynamically bound and the stack is built up manually by Max at runtime based on some assumptions (in this case that a floating point number is a double). The other is a clearly prototyped API function which the compiler can handle as defined. There's nothing precluding the introduction of an outlet_double() in the future, nor is this logically inconsistent. The heritage for passing doubles on the stack for our dynamically bound function pointers comes from the PPC architecture passing both floats and doubles on the stack as double precision values. We decided to keep this convention on Intel.
      Note that in Max floats are currently always passed between objects at 32bit resolution. This might be increased in a future version (for which our use of doubles on the stack will prove useful). However, for now it is a limitation.
      Hope this sheds a bit of light on what's going on. If you really want to avoid this float/double confusion, simply define all your functions with A_GIMME and manage the atoms which are passed between objects in your object. The other method signatures and outlet calls are really there only for convenience.
      -Joshua
    • Mar 16 2006 | 9:03 pm
      > Basically these are two different things. One is has to do with a > function pointer (not known at compile time as far as Max is concerned) > which is dynamically bound and the stack is built up manually by Max at > runtime based on some assumptions (in this case that a floating point > number is a double). The other is a clearly prototyped API function > which the compiler can handle as defined. There's nothing precluding the > introduction of an outlet_double() in the future, nor is this logically > inconsistent. The heritage for passing doubles on the stack for our > dynamically bound function pointers comes from the PPC architecture > passing both floats and doubles on the stack as double precision values. > We decided to keep this convention on Intel. > > Note that in Max floats are currently always passed between objects at > 32bit resolution. This might be increased in a future version (for which > our use of doubles on the stack will prove useful). However, for now it > is a limitation.
      Thanks for your precisions
      > Hope this sheds a bit of light on what's going on. If you really want to > avoid this float/double confusion, simply define all your functions with > A_GIMME and manage the atoms which are passed between objects in your > object. The other method signatures and outlet calls are really there > only for convenience. Not especially, A_FLOAT is more convenient... I'll use double for inlets.
      That was just to point the difference and try to understand.
      Best regards, CHris