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

Mar 14, 2006 at 2:11pm

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

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:
#P window setfont “Sans Serif” 9.;
#P flonum 261 51 35 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 175 48 35 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 192 117 66 9109513 testobj;
#P connect 1 0 0 0;
#P connect 1 0 0 1;
#P connect 1 0 0 2;
#P connect 1 0 0 3;
#P connect 1 0 0 4;
#P connect 2 0 0 0;
#P connect 2 0 0 1;
#P connect 2 0 0 2;
#P connect 2 0 0 3;
#P connect 2 0 0 4;
#P window clipboard copycount 3;

#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);
}

#24878
Mar 14, 2006 at 2:15pm

On Windows, arguments using float values must be doubles.

jb

#72544
Mar 14, 2006 at 2:17pm

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

#72545
Mar 14, 2006 at 2:25pm

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_

#72546
Mar 14, 2006 at 2:27pm

I need to type faster, 3rd place damn it ;-)

t_

#72547
Mar 14, 2006 at 2:29pm

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

#72548
Mar 14, 2006 at 2:36pm

#72549
Mar 14, 2006 at 2:42pm

Yes, go ahead and use double for both.

jb

#72550
Mar 14, 2006 at 2:49pm

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/

#72551
Mar 14, 2006 at 3:02pm

> 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

#72552
Mar 14, 2006 at 6:27pm

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/

#72553
Mar 14, 2006 at 6:49pm

> 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

#72554
Mar 16, 2006 at 5:44pm

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

#72555
Mar 16, 2006 at 7:55pm

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

#72556
Mar 16, 2006 at 9:03pm

> 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

#72557

You must be logged in to reply to this topic.