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 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

* using objc_msgSend() or objc_msgSend_stret() directly. Cast objc_msgSend() to a function pointer type that matches your method's signature, then make the call.


Typecasting only works for that if the signature is known at compile-time. If you won't know the signature until runtime, you'll need to either use the marg_* macros and pass the resulting marg_list struct to objc_msgSendv(). Or, use ffi or ffcall to call objc_msgSend().


That last option (ffi/ffcall) is the most complex, but it's the only way I've found to implement a "foreign" language (Perl in my case) subclass of an Objective-C class, and allow the "foreign" language to call super's methods.

Hmm. I looked at libffi but the release notes said it didn't support vararg functions. I'll have to look again. Maybe I'll take a look at your code. :-)


Incidentally, I'm writing an Objective-C wrapper for OCaml, so your code is more than a little bit relevant.

The problem I found was that there's no "v" (at least none that's documented) equivalent to the objc_msgSendSuper() function. What I settled on doing was using ffcall to call the "normal" msgSendSuper functions, rather than the marg_* macros and the "v" functions.

if you have a pointer to the object's Class can't you use the super_class field to get access to superclass methods? Maybe I'm missing something?


Cheers,
-n8

--
>>>-- Nathaniel Gray -- Caltech Computer Science ------>
>>>-- Mojave Project -- http://mojave.cs.caltech.edu -->


_______________________________________________ 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>)



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.