代码之家  ›  专栏  ›  技术社区  ›  Stephen Furlani

NSInvocation未将指针传递到c++数组

  •  2
  • Stephen Furlani  · 技术社区  · 15 年前

    我认为我犯了一个根本性的错误,但我一辈子都看不到。

    我从C++类(锁定)中调用ObjtoE-C对象的方法。我使用NSInvocation来防止我不得不编写数百个方法来访问这个其他对象中的数据。

    这些是我要经历的步骤。这是我第一次打电话,我想过去 s2

    float s2[3];
    id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
    _view->_callPixMethod(@selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
    

    这是正在调用的视图方法

    invokeUnion View::_callPixMethod(SEL method, int nArgs, id args[])
    {
        DataModule* data;
        DataVisitor getdata(&data);
        getConfig()->accept(getdata);
        invokeUnion retVal;
        retVal.OBJC_ID = data->callPixMethod(_index, _datasetKey, method, nArgs, args);
        return retVal;
    }
    

    union invokeUnion {
    id OBJC_ID;
    int intValue;
    float floatValue;
    bool boolValue;
    };
    

    这是数据对象中的方法(pthread locked with lock()和unlock());

    id DataModule::callPixMethod(int index, std::string predicate, SEL method, int nArgs, id args[] )
    {
        // May Block
        DCMPix *pix =[[getSeriesData(predicate) pix] objectAtIndex:index];
    
        lock();
    
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        NSMethodSignature *signature;
        NSInvocation *invocation;
    
        signature = [DCMPix instanceMethodSignatureForSelector:method];
        invocation = [NSInvocation invocationWithMethodSignature:signature];
    
        [invocation setSelector:method];
        [invocation setTarget:pix];
    
        if (nArgs > 0) for (int n = 0; n < nArgs; n++) {
            SFLog(@"invocation: i=%d, *ptr=0x%x, valf=%f, vald=%d",n,args[n],*args[n],*args[n]);
            [invocation setArgument:args[n] atIndex:2+n];
        }
    
        id retVal;
    
        [invocation invoke];
        [invocation getReturnValue:&retVal];
    
        [pool release];
    
        unlock();
    
        return retVal;
    }
    

    DCMPix对象(我无法修改,它是库的一部分)中的方法如下:

    -(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d pixelCenter: (BOOL) pixelCenter
    {
        if( pixelCenter)
        {
            x -= 0.5;
            y -= 0.5;
        }
    
        d[0] = originX + y*orientation[3]*pixelSpacingY + x*orientation[0]*pixelSpacingX;
        d[1] = originY + y*orientation[4]*pixelSpacingY + x*orientation[1]*pixelSpacingX;
        d[2] = originZ + y*orientation[5]*pixelSpacingY + x*orientation[2]*pixelSpacingX;
    }
    
    -(void) convertPixX: (float) x pixY: (float) y toDICOMCoords: (float*) d
    {
        [self convertPixX: x pixY: y toDICOMCoords: d pixelCenter: YES];
    }
    

    当它试图访问时崩溃了 d[0] . BAD_EXC_ACCESS

    我越来越记不清我的指针了。这两个浮点值看起来不错(其他方法中的其他信息也是如此),但这是唯一一个要求 float* 作为参数。据我所知 convertPixX: out 值。。。我想。

    不管怎样,任何有见识的人都会非常感激的。

    float *s2 = new float[3];
    void* ps2 = &s2;
    id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&ps2};
    _view->_callPixMethod(@selector(convertPixX:pixY:toDICOMCoords:),3,args2s);
    

    但这给了我们一个 SIGKILL

    不管怎样。。。指针!跨语言!啊!

    1 回复  |  直到 15 年前
        1
  •  0
  •   JeremyP    15 年前

    数组不是指针。尝试添加以下行

    NSLog(@"%p, %p", s2, &s2);
    

    id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2};
    

    s2和&s2都是数组中第一个浮点的地址,因此在执行以下操作时:

    [invocation setArgument:args[n] atIndex:2+n];
    

    对于n=2,您不是在复制指向第一个浮点的指针,而是复制第一个浮点,如果一个id是64位宽的,则可能是前两个浮点。

    若要解决此问题,此方法可能有效(未经测试)。

    float s2[3];
    float* s2Pointer = s2;
    id args2s[] = {(id)&_start.x(),(id)&_start.y(),(id)&s2Pointer};
    _view->_callPixMethod(@selector(convertPixX:pixY:toDICOMCoords:),3,args2s);