Пример #1
0
static VALUE
rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
{
    char ocname[512] = { '\0' };
    if (!rb_vm_generate_objc_class_name(name, ocname, sizeof ocname)) {
	goto no_more_classes;
    }

    Class ocklass = objc_allocateClassPair((Class)super, ocname, 0);
    if (ocklass == NULL) {
	goto no_more_classes;
    }

    long version_flag = RCLASS_IS_RUBY_CLASS;
    if (flags == T_MODULE) {
	version_flag |= RCLASS_IS_MODULE;
    }
    RCLASS_SET_VERSION(ocklass, version_flag);

    objc_registerClassPair(ocklass);

    if (klass != 0 && super != 0) {
	rb_objc_class_sync_version(ocklass, (Class)super);
    }

    return (VALUE)ocklass;

no_more_classes:
    rb_raise(rb_eRuntimeError, "can't create new classes");
}
Пример #2
0
//Create an class named "AppDelegate", and return it's name as an instance of class NSString
void *createAppDelegate() {
  Class mySubclass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
  struct objc_selector *selName = sel_registerName("application:didFinishLaunchingWithOptions:");
  class_addMethod(mySubclass, selName, (void(*))applicationdidFinishLaunching, nil);
  objc_registerClassPair(mySubclass);
  return objc_msgSend(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "AppDelegate");
}
Пример #3
0
void * createDelegate() {
  Class superclass = (Class) objc_getClass("NSObject");
  Class DataSource = objc_allocateClassPair(superclass, "Delegate", 0);
  class_addMethod(DataSource, sel_registerName("tableView:didSelectRowAtIndexPath:"), (void(*))tableView_didSelectRowAtIndexPath, nil);
  objc_registerClassPair(DataSource);
  return class_createInstance(DataSource, 0);
}
Пример #4
0
int main(int argc,const char* argv[])
{
    //新创建一个Class对象,继承于NSObject,名字叫NSPower(用于注册一个Class,Class的名字叫NSPower)
    Class powerCls = objc_allocateClassPair(objc_getClass("NSObject"), "NSPower", 0);
    //定义一个SEL,也就是OC里面的Selector,我理解为一个方法的Key,通过这个名字可以找到一个对应的方法实现函数
    SEL selFun = sel_registerName("fun");
    
    //为这个Class添加一个方法,名字叫fun,实现为power_fun(之前声明的一个C函数)
    //后面这个字符串是干嘛的呢?用来说明参数的,OC语言特别为每种参数类型指定了一个编码
    //比如V@:的意思是,返回值是void,第一个参数是id,第二个参数是SEL
    class_addMethod(powerCls, selFun, (IMP)power_fun, "V@:");
    
    //注册这个Class,从此以后,你就可以使用NSPower这个名字来创建一个类的实例了
    objc_registerClassPair(powerCls);
    
    //以下代码就是创建一个NSPower的实例,并且调用fun方法
    //得到一个class的实例
    Class cls = objc_getClass("NSPower");
    //对这个class发送alloc消息,创建一个class对象
    id obj = objc_msgSend((id)cls,sel_registerName("alloc"));
    //对这个对象发送一个fun消息,这样会调用到之前的power_fun方法
    objc_msgSend(obj,selFun);
    
    return 0;
}
Пример #5
0
void *createDataSource() {
  Class superclass = (Class) objc_getClass("NSObject");
  Class DataSource = objc_allocateClassPair(superclass, "DataSource", 0);
  class_addMethod(DataSource, sel_registerName("tableView:numberOfRowsInSection:"), (void(*))tableView_numberOfRowsInSection, nil);
  class_addMethod(DataSource, sel_registerName("tableView:cellForRowAtIndexPath:"), (void(*))tableView_cellForRowAtIndexPath, nil);
  objc_registerClassPair(DataSource);
  return class_createInstance(DataSource, 0);
}
Пример #6
0
Class RegisterClass(old_class* cls, bool hasExt)
{
	LOG << "Processing old ObjC class " << cls->name << std::endl;
	
	const old_class* meta = cls->isa.cls;
	Class conv, super;
	auto & g_classPointers = getClassPointers();
	/*
	old_class* psuper = cls->super_class.cls;
	auto itSuper = g_classPointers.find(psuper); // TODO: may not be needed, should always be a string

	if (itSuper != g_classPointers.end())
		super = itSuper->second;
	else
		super = reinterpret_cast<Class>(psuper);
	*/

	super = (Class) objc_getClass(cls->super_class.name);
	LOG << "...with superclass @" << super << std::endl;
	conv = objc_allocateClassPair(super, cls->name, 0);
	
	if (cls->methodList)
		ConvertMethodListGen(conv, cls->methodList);
	if (meta->methodList)
		ConvertMethodListGen(object_getClass(id(conv)), meta->methodList);
	if (cls->ivars)
		ConvertIvarList(conv, cls->ivars);
	if (cls->protocols)
		AddClassProtocols(conv, cls->protocols);
	
	if (hasExt && cls->ext && cls->ext->propertyLists)
	{
		LOG << "Class has EXT and a property list/lists\n";
		//if (cls->info & CLS_NO_PROPERTY_ARRAY)
		if (true)
		{
			ConvertProperties(cls->ext->propertyList, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
		}
		else
		{
			for (size_t i = 0; cls->ext->propertyLists[i] != nullptr; i++)
			{
				const old_property_list* l = cls->ext->propertyLists[i];
				ConvertProperties(l, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
			}
		}
	}
	
	objc_registerClassPair(conv);
	g_classPointers[cls] = conv;
	g_classPointers[cls->name] = conv;

	LOG << "ObjC class " << cls->name << " @" << conv << std::endl;
	
	return conv;
}
Пример #7
0
Class RegisterClass(const class_t* cls, intptr_t slide)
{
	LOG << "Processing ObjC class " << cls->data()->className << std::endl;
	
	const class_t* meta = cls->isa;
	Class conv, super;
	auto itSuper = g_classPointers.find(cls->superclass);

	if (itSuper != g_classPointers.end())
		super = itSuper->second;
	else
		super = reinterpret_cast<Class>(cls->superclass);
	
	LOG << "...superclass is @" << super << std::endl;
	assert(objc_getClass(cls->data()->className) == nullptr);
	conv = objc_allocateClassPair(super, cls->data()->className, 0);
	
	const class_ro_t* ro = cls->data();
	const class_ro_t* roMeta = meta->data();
	
	if (ro->baseMethods)
		ConvertMethodListGen(conv, ro->baseMethods);
	if (roMeta->baseMethods)
		ConvertMethodListGen(object_getClass(id(conv)), roMeta->baseMethods);
	if (ro->ivars)
		ConvertIvarList(conv, ro->ivars);
	if (ro->baseProtocols)
		AddClassProtocols(conv, ro->baseProtocols, slide);
	if (ro->baseProperties)
	{
		ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
	}
	
	// conv->instance_size = ro->instSize;
	// conv->isa->instance_size = roMeta->instSize;
	
	objc_registerClassPair(conv);
	
	LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl;
	g_classPointers[cls] = conv;
	g_classPointers[cls->isa] = object_getClass(id(conv));
	
	return conv;
}
Пример #8
0
void* UndefMgr::generateNew(const char* name)
{
	bool isClass = (strncmp(name, "OBJC_CLASS", 10) == 0);
	bool isMetaClass = (strncmp(name, "OBJC_METACLASS", 14) == 0);

	if (isClass || isMetaClass)
	{
		// Strip the OBJC_CLASS_$_ or OBJC_METACLASS_$_
		name =  &name[(isMetaClass) ? 17 : 13];

		// Objective-C class or metaclass info
		static std::map<std::string, Class> undefClasses;
		Class classStub = nullptr;
		auto classIter = undefClasses.find(name);
		if (classIter != undefClasses.end())
		{
			classStub = classIter->second;
		}
		else if (NULL == (classStub = (Class)objc_getClass(name)))
		{
			classStub = objc_allocateClassPair(nullptr, name, 0);
			if (isMetaClass)
			{
				// Put in a dummy initialize method that lets us know the class got used
				IMP imp = reinterpret_cast<IMP>(&UndefinedClassInitialize);
				SEL sel = sel_registerTypedName_np("initialize", NULL);
				class_addMethod(object_getClass(reinterpret_cast<id>(classStub)), sel, imp, NULL);
			}
			objc_registerClassPair(classStub);
			Darling::MachOMgr::instance()->registerNativeClass(object_getClass(reinterpret_cast<id>(classStub)));
			Darling::MachOMgr::instance()->registerNativeClass(classStub);
			fprintf(stderr, "Undef class for class %s at %p\n", class_getName(classStub), classStub);
			undefClasses[name] = classStub;
		}

		return (isClass) ? classStub : object_getClass(reinterpret_cast<id>(classStub));
	}
	else if (strncmp(name, "OBJC_IVAR", 9) == 0)
	{
		// Objective-C ivar
		typedef struct 
		{
			const char *name;
			const char *type;
			int         offset;
		} objc_ivar;

		objc_ivar *ivarStub = new objc_ivar;
		ivarStub->name = &name[12];
		ivarStub->type = "";
		ivarStub->offset = 0;
		return ivarStub;
	}
	else
	{
		// Generate a function stub
		UndefinedFunction * uf = new UndefinedFunction();
		uf->init(name);
		return uf->getPointer();
	}
}
Пример #9
0
Class RegisterClass(const class_t* cls, intptr_t slide, uint32_t image_index)
{
	if (nullptr == cls)
	{
		return nullptr;
	}

	auto & g_classPointers = getClassPointers();
	auto itClass = g_classPointers.find(cls);
	if (itClass != g_classPointers.end())
	{
		LOG << "Found existing class @" << itClass->second << std::endl;
		return itClass->second;
	}

	Class super = RegisterClass(cls->superclass, slide, image_index);

	LOG << "...superclass is @" << super << std::endl;
	if (nullptr != super)
	{
		LOG << "...superclass name " << (((uintptr_t)super != (uintptr_t)cls->superclass) ? cls->superclass->data()->className : class_getName(super)) << std::endl;
		LOG << "...super name " << class_getName(super) << std::endl;
	}

	if (nullptr == cls->data())
	{
		// TODO: Is this a bad pointer filled in, or are we supposed to do something different with this?
		// This is from when we call RegisterClass recursively sometimes...
		std::cerr << "Error - Null class data at class @" << cls << std::endl;
		return nullptr;
	}

	if (nullptr == cls->data()->className)
	{
		// TODO: Is this a bad pointer filled in, or are we supposed to do something different with this?
		// This is from when we call RegisterClass recursively sometimes...
		std::cerr << "Error - Null class name at class @" << cls << std::endl;
		return nullptr;
	}

	LOG << "Processing ObjC class " << cls->data()->className << std::endl;

	Class sameClass = (Class)objc_getClass(cls->data()->className);
	if (nullptr != sameClass)
	{
		LOG << "Found a class with the same name @" << sameClass << std::endl;
		return sameClass;
	}

	LOG << "obj_allocateClassPair(" << super << ", " << cls->data()->className << ")" << std::endl;

	Class conv = objc_allocateClassPair(super, cls->data()->className, 0);

	if (nullptr == conv)
	{
		std::cerr << "Failed to allocate class " << cls->data()->className << std::endl;
		return nullptr;
	}

	Class meta = object_getClass(id(conv));

	const class_ro_t* ro = cls->data();

	if (ro->baseMethods)
		ConvertMethodListGen(conv, ro->baseMethods, image_index);
	if (g_classPointers.find(cls->isa) == g_classPointers.end())
	{
		const class_ro_t* roMeta = cls->isa->data();
		if (roMeta->baseMethods)
			ConvertMethodListGen(meta, roMeta->baseMethods, image_index);
	}
	if (ro->ivars)
		ConvertIvarList(conv, ro->ivars);
	if (ro->baseProtocols)
		AddClassProtocols(conv, ro->baseProtocols, slide);
	if (ro->baseProperties)
	{
		ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
	}

	// conv->instance_size = ro->instSize;

	objc_registerClassPair(conv);
	
	LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl;
	g_classPointers[cls] = conv;
	g_classPointers[conv] = conv;
	g_classPointers[meta] = meta;

	return conv;
}
Пример #10
0
	bool NSGLWindow::initialize()
	{
		// Strong reference to the class of the AppDelegate (same as [AppDelegate class])
		static Class appDelClass = nullptr;
		if (not appDelClass)
		{
			appDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
			class_addMethod(appDelClass, sel_getUid("applicationDidFinishLaunching:"), (IMP)OnAppDidFinishLaunching, "i@:@");
			objc_registerClassPair(appDelClass);
		}

		// Tell the runtime to create a new class, a subclass of 'NSOpenGLView' named 'YView'.
		static Class viewClass = nullptr;
		if (not viewClass)
		{
			viewClass = objc_allocateClassPair((Class)objc_getClass("NSOpenGLView"), "YView", 0);

			// Tell the runtime to add functions for various events to our custom view.
			class_addMethod(viewClass, sel_getUid("drawRect:"), (IMP)NSGLWindow::OnDrawRect, "v@:");
			class_addMethod(viewClass, sel_getUid("mouseDown:"), (IMP)NSGLWindow::OnMouseDown, "v@:");
			//class_addMethod(viewClass, sel_getUid("close:"), (IMP)NSGLWindow::OnWindowClose, "v@:");

			// And again, we tell the runtime that this class is now valid to be used.
			// At this point, the application should run and display the screenshot shown below.
			objc_registerClassPair(viewClass);
		}

		cmacs_simple_msgSend((id)objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
		if (not NSApp)
		{
			std::cerr << "Failed to initialized NSApplication...  terminating..." << std::endl;
			return false;
		}

		// Create the app delegate
		static AppDelegate* appDelObj = nullptr;
		if (not appDelObj)
		{
			appDelObj = (AppDelegate*)cmacs_simple_msgSend((id)objc_getClass("AppDelegate"), sel_getUid("alloc"));
			appDelObj = (AppDelegate*)cmacs_simple_msgSend((id)appDelObj, sel_getUid("init"));

			cmacs_void_msgSend1(NSApp, sel_getUid("setDelegate:"), appDelObj);

			// Launch main loop
			//cmacs_void_msgSend(NSApp, sel_getUid("run"));
		}

		appDelObj->window = cmacs_simple_msgSend((id)objc_getClass("NSOpenGLWindow"), sel_getUid("alloc"));

		/// Create an instance of the window.
		appDelObj->window = cmacs_window_init_msgSend(appDelObj->window, sel_getUid("initWithContentRect:styleMask:backing:defer:"), (CMRect){ {0,0},{1024,460}},
			(NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask), 0, false);
	    
		/// Create an instance of our view class.
		///
		/// Relies on the view having declared a constructor that allocates a class pair for it.
		id view = cmacs_rect_msgSend1(cmacs_simple_msgSend((id)objc_getClass("YView"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (CMRect){ {0, 0}, {640, 480} });

		// here we simply add the view to the window.
		cmacs_void_msgSend1(appDelObj->window, sel_getUid("setContentView:"), view);
		cmacs_simple_msgSend(appDelObj->window, sel_getUid("becomeFirstResponder"));

		// Shows our window in the bottom-left hand corner of the screen.
		//cmacs_void_msgSend1(appDelObj->window, sel_getUid("makeKeyAndOrderFront:"), appDelObj);

		return true;
	}