NSIncation 未将指针传递给 c++大批

发布于 2024-09-25 13:19:18 字数 3170 浏览 2 评论 0原文

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

我正在从 C++ 类(已锁定)中调用 Objective-C 对象的方法。我使用 NSInitation 来防止我必须编写数百个方法来访问另一个对象中的数据。

这些是我正在经历的步骤。这是我的第一次通话,我想传递 s2。我无法真正提供一个可编译的示例,但希望这只是我的一个 DUHRRRRR 问题。

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

这是被称为 Invoke Union 的 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;
}

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

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

这是数据对象中的方法(pthread用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: 方法是从为 Mac OS 9 编写的 C 程序转换过来的...这就是为什么它要求 c 数组作为 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 - 而且我确信它是伪造的且错误的。 ...但我尝试过。

无论如何……指点!跨语言!啊!

谢谢,

I think I'm making just a fundamental mistake, but I cannot for the life of me see it.

I'm calling a method on an Objective-C object from within a C++ class (which is locked). I'm using NSInvocation to prevent me from having to write hundreds methods just to access the data in this other object.

These are the steps I'm going through. This is my first call, and I want to pass s2. I can't really provide a compilable example, but hopefully it's just a DUHRRRRR problem on my part.

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

This is the View method being called

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 is a union so I can get the float value returned by NSInvocation.

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

This is the method in the data Object (pthread locked with lock() and 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;
}

The method in the DCMPix object (which I can't modify, it's part of a library) is the following:

-(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];
}

It's crashing when it tries to access d[0]. BAD_EXC_ACCESS which I know means it's accessing released memory, or memory outside of it's scope.

I'm getting lost keeping track of my pointers to pointers. the two float values come across fine (as does other info in other methods) but this is the only one asking for a float* as a parameter. From what I understand the convertPixX: method was converted over from a C program written for Mac OS 9... which is why it asks for the c-array as an out value... I think.

Anyway, any insight would be greatly appreciated.

I've tried sending the value like this:

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

But that gives a SIGKILL - plus I'm sure it's bogus and wrong. ... but I tried.

anyway... pointers! cross-language! argh!

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世俗缘 2024-10-02 13:19:19

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

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

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

An array is not a pointer. Try adding the following line

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

just above.

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

s2 and &s2 are both the address of the first float in your array, so when you do:

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

for n = 2, you are not copying in a pointer to the first float, but the first float, possibly the first two floats if an id is 64 bits wide.

Edit:

To fix the issue, this might work (not tested).

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 is a real pointer that will give you the double indirection you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文