编辑:对于未来googlers abarnert的回答是有效的NSHIObject(来自HIToolbox,HI代表人机界面),我可以找到更多关于此的文档,这是apple.com上唯一提到的(那里)是关于这一点https://www.google.com/#q=%22NSHIObject%22+site%3Aapple.com&filter=0)的一个名为NSHI对象的类的ZERO,ZIP,NADA文档 在对象c中,如果我有以下http://lists.apple.com/archives/webkitsdk-dev/2010/Sep/msg00007.html对该对象不起作用,则不会创建NSWindow。是的苹果API文件。
NSWindow.initWithWindowRef_(nshi_object)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: Expecting instance of NSWindow as self, got one of NSHIObject
关于加载从wxPython
给出的指针的原始问题C代码
// our data
int a = 42;
// create a pointer to that data
int *p = &a;
// p now contains the address (say 1776) and that address has the integer 42
// get the data back
int ret_a = *p;
// now if we already have an address
int* manual_pointer = (int*) 1776;
int man_a = *manual_pointer;
printf("%d,%d\n", ret_a, man_a);
如何在pyobjc中执行此语法?我看到它提到了here
More complex types can be represented using longer type strings:
a pointer to some type is _C_PTR followed by the type string of the pointed-to type.
那我该怎么办?这个(如果对象类型是NSInt)?
arg = _C_PTR + "NSInt" + "1776"
目标C代码(稍后添加) 请注意,你必须以某种方式将其注入python进程,否则它将无法正常工作
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
char line[2048];
// this will store are address
long adr;
printf("According to \n- http://forums.wxwidgets.org/viewtopic.php?f=23&t=31778\n- http://forums.wxwidgets.org/viewtopic.php?f=23&t=18645\n");
printf("This will prompt you for a pointer address; please paste in the long you received from GetHandle()\n");
printf("Please enter pointer address: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%ld", &adr);
printf("Using address: %ld\n", adr);
printf("Grabbing view...");
// our NSView
NSView *view = (__bridge NSView *)((void *)adr);
NSRect f = view.frame;
int w = f.size.width;
int h = f.size.height;
printf("Size(%d, %d)", w, h);
}
return 0;
}
答案 0 :(得分:3)
根据你对bbum的回答的评论:
问题是我从C ++库(wxPython)获取指针地址,指向我想要的NSView对象。
为此,只需使用objc_object
构造函数:
view = objc.objc_object(c_void_p=ptr)
当然,我不认为wxPython
为您获取指针的任何函数提供ctypes.c_void_p
值。我不知道 给你的是什么,但最可能的是int
,在这种情况下你可以这样做:
view = objc.objc_object(c_void_p=ctypes.c_void_p(ptr))
您没有提到您正在使用的PyObjC版本。如果它在2.5之前(您可以检查objc.version
),则必须手动构建PyCapsule对象,或者从桥的另一侧执行此操作。我没有旧的副本来测试,或旧的文档,所以这是来自内存,但它看起来像这样:
view = NSView.objectWithSomethingOrOther_(ptr)
同时,从你原来的问题:
arg = _C_PTR + "NSInt" + "1776"
我不确定你为什么要在第一时间建立一个类型字符串,但是......
指向某个类型X的指针的类型字符串是_C_PTR
,后跟X的类型字符串,而不是X的名称。此外,没有类型NSInt
。如果您的意思是NSNumber
类,则可以使用_C_ID
(就像在原生ObjC中使用id
而不是NSNumber *
一样)。如果您的意思是整数类型NSInteger
,那就是_C_PTR + _C_NSInteger
。如果你的意思是一个没有特殊名称的整数类型,你必须找出它是typedef的类型并使用它 - 例如,_C_PTR + _C_LNG
将适用于64位的NSInteger *
苹果机。
同时,类型字符串命名一个类型,而不是一个值,所以如果1776
应该是指向的位置,或者该位置的值,或者我能想到的其他任何东西,这甚至没有意义。
最后,我不知道你的C代码(其中没有任何ObjC)应该是什么样的,但我愿意打赌,如果你实际运行它,它将会出现段错误。
与此同时,根据您的评论和your code,您尝试做的事实际上没有任何意义,也无法奏效。您现在成功完成这一事实就是您崩溃的原因。
每个进程都有自己的虚拟地址空间。当您从一个进程的地址空间获取指针并在另一个进程中使用它时,它不指向相同的对象;它指向完全不同的对象,或者根本没有任何对象。这就是你得到那个段错误的原因:0x000000007a6e5c90
指向wxPython程序地址空间中的NSView
,但是同一地址指向交互式解释器地址空间中未映射的内存。
此外,虽然有API可以映射来自其他进程的内存区域,或直接读取和写入其他进程的地址空间,但这对您没有帮助,因为如果有任何指针 - 包括不透明的内部指针 - 内您指向的对象,您还必须明确映射那些。而且,在ObjC对象的情况下,即使 也不起作用,因为ObjC依赖于(进程 - )全局对象工作空间。 (理论上,您可以编写直接操作其他进程的ObjC工作区的C代码,而不是使用ObjC,但是......您不想这样做。)
如果要从不同进程中的一个进程访问NSView
,有两种方法可以执行此操作。您必须使用高级跨进程API来操作窗口,或者您必须将代码注入其他进程并触发它(例如,F-Script Anywhere所做的) - 或者,作为一个小的变体第二个,作为调试器附加到另一个进程。
但如果您自己编写这两个程序,那么可以采用更清晰的方式。编写您的GUI应用程序以某种方式可外部控制。 Mac上的一种方法是使用AppleScript界面。使用CocoaScripting导出一个API,允许其他应用程序执行诸如移动窗口之类的操作。然后使用appscript或ScriptingBridge,或通过NSAppleScript使用双语言方法来使用该API,而不是尝试直接与NSView对象对话。 (如果你真的想,你可以通过CocoaScripting导出整个NSView界面,但这可能不是最好的答案。)
答案 1 :(得分:2)
Python根本不处理指针;事实上,它积极地阻止它们在各方面的使用。您可以使用id()
函数来检索Python对象的地址,但是没有相应的函数可以采用其他方式(这不是一个笑话)。
现在,假设您有一个指向C语言的指针,您应该能够使用ctypes模块描述某些内容,然后将该地址视为指针并随意解码。但这很棘手。
不是最具体的例子,但知道Python,Objective-C和熟悉ctypes的人的维恩图是一个相当小的群体(这是为什么你通常更好地坚持原生ObjC的一个重要原因对于iOS / Cocoa)。