Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Sending floats using objc_msgSendv




On Aug 11, 2005, at 12:41 AM, Nathaniel Gray wrote:

On Aug 10, 2005, at 6:56 PM, Sherm Pendley wrote:


On Aug 10, 2005, at 9:32 PM, Greg Parker wrote:



On Aug 10, 2005, at 6:02 PM, Nathaniel Gray wrote:



Is there any way to send float or double arguments to a method designated at runtime? I've tried using objc_msgSendv, casting it in various ways, and using -performv::, but nothing works.



Using objc_msgSendv() properly requires knowledge of your platform's ABI. In particular, floating-point values must be stored in a special place in the marg_list on PowerPC. objc-msg- ppc.s notes some of the details.




I think those details are pretty well hidden by the marg_* macros though. I've used method_getArgumentInfo() to get the offset of the argument, and marg_setValue() to set it before calling objc_msgSendv(). It worked fine with all sorts of types, including floats and doubles.



Really? That's exactly what I'm doing. For a test case I wrote a class OCOCTestCall with a class method


+ (float)callFloat:(float)x
{
    eprintf("Got float: %f\n", x);
    return x+1.0;
}

Then I call it with this code:

void test1_1mini() {
    id nc = NSClassFromString(@"OCOCTestCall");
    SEL sel = @selector(callFloat:);
    marg_list margs;
    int offset;
    Method method;
    const char* argtype;
    union {float f; id i;} u;

    u.f = 123.45f;

    method = class_getInstanceMethod(nc->isa, sel);
    /* Set up the marg_list */
    marg_malloc(margs, method);
    method_getArgumentInfo(method, 0, &argtype, &offset);
    marg_setValue(margs, offset, id, nc);
    method_getArgumentInfo(method, 1, &argtype, &offset);
    marg_setValue(margs, offset, SEL, sel);
    method_getArgumentInfo(method, 2, &argtype, &offset);
    marg_setValue(margs, offset, float, u.f);

/* Plain msgSendv */
u.i = objc_msgSendv(nc, sel, method_getSizeOfArguments(method), margs);
printf( "msgSendv: float u.f = %f\n", u.f );


/* Cast function type to return float */
u.f = ((float_msgSendv)objc_msgSendv)(nc, sel,
method_getSizeOfArguments(method), margs);
printf( "((float_msgSendv)objc_msgSendv): float u.f = %f\n", u.f );


    /* Send as message */
    u.i = [nc performv:sel :margs];
    printf( "[nc performv::]: Float u.f = %f\n", u.f );
}

Here's what I get:

[n8gray@golux test]$ ./ctest1
Got float: 0.000000
msgSendv: Float f = 0.000000
Got float: 0.000000
((float_msgSendv)objc_msgSendv): Float f = 1.000000
Got float: 0.000000
[nc performv::]: Float f = 0.000000

Adding this variant works just fine:

    /* Plain msgSend */
    u.f = ((float (*) (id, SEL, float))objc_msgSend)(nc, sel, u.f);
    printf( "objc_msgSend: float u.f = %f\n", u.f );

Got float: 123.449997
objc_msgSend: float u.f = 124.449997

If I change your margs set up code to the following, I get the expected result:

    /* Set up the marg_list */
    marg_malloc(margs, method);
    method_getArgumentInfo(method, 0, &argtype, &offset);
    marg_setValue(margs, offset, id, nc);
    method_getArgumentInfo(method, 1, &argtype, &offset);
    marg_setValue(margs, offset, SEL, sel);
    method_getArgumentInfo(method, 2, &argtype, &offset);
    marg_setValue(margs, offset, float, u.f);
    ((double*)margs)[0] = u.f;

Got float: 123.449997
objc_msgSend: float u.f = 124.449997
Got float: 123.449997
msgSendv: float u.f = 0.000000
Got float: 123.449997
((float_msgSendv)objc_msgSendv): float u.f = 124.449997
Got float: 123.449997
[nc performv::]: Float u.f = 0.000000

As Greg said, go read objc-msg-ppc.s to understand why. The relevant comment describes the true layout of margs, which has an array of 13 doubles at the beginning, which are animage of the floating point parameter registers that must be set. In this case, the float parameter x is supposed to be in fp0.

You can download this source from here:

http://www.opensource.apple.com/darwinsource/tarballs/apsl/ objc4-266.tar.gz

- Patrick

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Objc-language mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/objc-language/email@hidden

This email sent to email@hidden
References: 
 >Sending floats using objc_msgSendv (From: Nathaniel Gray <email@hidden>)
 >Re: Sending floats using objc_msgSendv (From: Greg Parker <email@hidden>)
 >Re: Sending floats using objc_msgSendv (From: Sherm Pendley <email@hidden>)
 >Re: Sending floats using objc_msgSendv (From: Nathaniel Gray <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.