NSIncation 未将指针传递给 c++大批
我认为我犯了一个根本性的错误,但我一生都看不到这一点。
我正在从 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
数组不是指针。尝试在上面添加以下行
。
s2 和 &s2 都是数组中第一个浮点数的地址,因此当您这样做时:
对于 n = 2,您不是复制指向第一个浮点数的指针,而是复制第一个浮点数,可能是前两个浮点数,如果id 是 64 位宽。
编辑:
要解决该问题,这可能有效(未经测试)。
s2Pointer 是一个真正的指针,它将为您提供所需的双重间接寻址。
An array is not a pointer. Try adding the following line
just above.
s2 and &s2 are both the address of the first float in your array, so when you do:
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).
s2Pointer is a real pointer that will give you the double indirection you need.