NSInvocation没有将指针传递给c ++数组

时间:2010-10-01 12:07:20

标签: c++ objective-c pointers memory-management nsinvocation

我认为我只是犯了一个根本性的错误,但我不能为我的生活看到它。

我在C ++类(已锁定)中调用Objective-C对象上的方法。我正在使用NSInvocation来阻止我只是为了访问这个其他对象中的数据而编写数百种方法。

这些是我正在经历的步骤。这是我的第一个电话,我想通过s2。我无法提供一个可编辑的例子,但希望这只是我的DUHRRRRR问题。

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

这是名为

的View方法
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;
}

Invoke Union是一个联合,因此我可以获得NSInvocation返回的浮点值。

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

这是数据对象中的方法(使用lock()和unlock()锁定pthread);

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:方法是从为Mac OS 9编写的C程序转换而来的...这就是为什么它要求将c-array作为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 个答案:

答案 0 :(得分:0)

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

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

就在上面。

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

s2和&amp; 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);

s2Pointer是一个真正的指针,它将为您提供所需的双重间接。