`
lobin
  • 浏览: 379427 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

Objective-C/C++

 

 

Objective-C由Brad Cox和Tom Love于1980年发明。

 

写道
There is no formal written standard for Objective-C or Objective-C++.

 

写道
The authoritative manual on traditional Objective-C (1.0) is “Object-Oriented Programming and the Objective-C Language”: http://www.gnustep.org/resources/documentation/ObjectivCBook.pdf is the original NeXTstep document.

 

 

写道
OBJECT-ORIENTED PROGRAMMING AND THE OBJECTIVE-C LANGUAGE
http://www.gnustep.org/resources/documentation/ObjectivCBook.pdf

 

 

写道
https://opensource.apple.com/releases/

 

 

Objective-C 1.0

Objective-C 1.0也称“traditional” Objective-C

写道
“traditional” Objective-C (also known as “Objective-C 1.0”)

 

Objective-C 2.0

 

 

从C到Objective-C

 

写道
https://github.com/apple-oss-distributions/objc4

 

 

写道
https://github.com/apple-oss-distributions/objc4/releases/tag/objc4-709.1

 

定义一个块变量

void (^LOG0) (NSString *);

void (^LOG) (NSString *, ...);

 

定义一个块变量并赋值

void (^LOG0) (NSString *) = ^(NSString *format) {

  //NSLog(format);

  NSLog(format, nil);

 

  NSLog(@"%@", format);

 

  //*

  NSString *str = [NSString stringWithFormat:@"%@", format];

    NSLog(@"%@",str);

    //*/

  };

 

void (^LOG) (NSString *, ...) = ^(NSString *format, ...) {

  va_list va;

  va_start(va, format);

  NSLogv(format, va);

  va_end(va);

  };

等号后面是一个表示块的字面量(block literal)。

 

定义一个块类型

typedef void (^log0) (NSString *);

typedef void (^logx) (NSString *, ...);

 

log0 fn_log0 = LOG0;

logx fn_logx = LOG;

 

调用

LOG0(@"Hello, world.");

LOG(@"%@: Hello, world.", @"Cocoa");

 

fn_log0(@"Hello, world.");

fn_logx(@"%@: Hello, world.", @"Cocoa");

对象

 

调用

通常其他语言在调用一个对象方法时,通常是这样的:

obj.firstMethod();

obj.secondMethod(2);

 

而在Objective-C/C++语言中则是这样:

[obj firstMethod];

[obj secondMethod: 2];

 

调用机制

Objective-C/C++和其他面向对象语言不一样的是,调用对象方法在Objective-C/C++语言中是向对象发送一个消息,并接收返回一个消息。不管哪种方式,都本质上都是对象间通信。

 

这实际上是通过objc_msgSend发送一个消息给对象obj。objc_msgSend是Objective-C/C++运行时库提供的函数。我们也可以通过objc_msgSend向对象发送和接收消息。

 

 

 

发送和接收消息

OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ )

    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);

 

OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)

    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);

 

typedef struct objc_selector *SEL;

 

objc_msgSendSuper

 

OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )

    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);

 

OBJC_EXPORT id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0);

 

除了以上方式,还可以通过performSelector、类似反射方式以及NSInvocation来向对象发送和接收消息。performSelector方式使用起来不是很方便,只能接受不超过2个的参数个数。

 

通过performSelector来向对象发送和接收消息

 

- (void) firstMethod;

- (void) secondMethod: (int) arg;

 

SimpleClass *obj = [SimpleClass new];

 

[obj performSelector:@selector(firstMethod)]; // just only without argument.

[obj performSelector:@selector(secondMethod:) withObject: (id) 2]; // just only with one argument.

 

通过类似反射方式来向对象发送和接收消息

- (void) firstMethod;

 

SimpleClass *obj = [SimpleClass new];

 

void (*firstMethod)(id, SEL); // - (void) firstMethod;

firstMethod = (void (*) (id, SEL)) [obj methodForSelector: @selector(firstMethod)];

firstMethod(obj, @selector(firstMethod));

 

通过NSInvocation来向对象发送和接收消息

 

- (void) secondMethod: (int) arg;

 

SimpleClass *obj = [SimpleClass new];

 

NSMethodSignature *secondMethodSignature = [obj methodSignatureForSelector: @selector(secondMethod:)];

  NSInvocation *secondMethodInvocation = [NSInvocation invocationWithMethodSignature: secondMethodSignature];

[secondMethodInvocation setTarget:obj];

[secondMethodInvocation setSelector:@selector(secondMethod:)];

 

int arg = 2000;

[secondMethodInvocation setArgument:&arg atIndex:2];

[secondMethodInvocation invoke];

写道
setArgument:atIndex: sets the specified argument to the value supplied. Every method has two hidden arguments, the target and selector (whose indices are 0 and 1), so the first argument that needs to be set is actually at index 2.

 

 

 

写道
In Objective-C, classes are defined in two parts:
■ An interface that declares the methods and instance variables of the class and names its superclass
■ An implementation that actually defines the class (contains the code that implements its methods)

 

 

 

NSObject

所有类的基类。NSObject不是所有其他类的隐式基类,需要显式的从NSObject继承。NSObject在Foundation中定义。

 

new方法覆盖(Override)

 

+ (id)new
{
	id handle = [super new];
	printf("new of BaseClass.\n");
	return handle;
}

alloc方法覆盖(Override)

 

+ (id)alloc
{
	id handle = [super alloc];
	printf("alloc of BaseClass.\n");
	return handle;
}

init方法覆盖(Override)

- (id)init
{
  self = [super init];
  printf("init of BaseClass.\n");
  return self;
}

 

Objective-C混合编程

 

Runtime

Objective-C/C++编程中可以直接调用Runtime运行时库提供的底层功能。比如直接调用objc_msgSend向对象发送消息。

 

objc_msgSend

- (void) firstMethod;

- (void) secondMethod: (int) arg;

 

SimpleClass *obj = [SimpleClass new];

 

SEL firstMethodSel = @selector(firstMethod);

objc_msgSend((id)obj, firstMethodSel); // [obj firstMethod];

 

SEL secondMethodSel = @selector(secondMethod:);

objc_msgSend((id)obj, secondMethodSel, 2); // [obj secondMethod: 2];

 

 

- (int) firstMethodWithRet;

- (int) secondMethodWithRet: (int) arg;

 

SEL firstMethodWithRetSel = @selector(firstMethodWithRet);

int ret = (int) objc_msgSend((id)obj, firstMethodWithRetSel); // int ret = [obj firstMethodWithRet];

printf("firstMethodWithRet. ret=%d\n", ret);

 

SEL secondMethodWithRetSel = @selector(secondMethodWithRet:);

ret = (int) objc_msgSend((id)obj, secondMethodWithRetSel, 2); // int ret = [obj secondMethodWithRet: 2];

printf("secondMethodWithRet. ret=%d\n", ret);

 

调用C静态链接库

 

#include <stddef.h>  
  
#if ! defined(QT)  
#define QT  
struct qt  
{  
  size_t size;  
  char data[];  
};  
  
struct qt* qt(int i);  
  
int qt_get(struct qt* v);  
  
int qt_destroy(struct qt* v);  
#endif 

 

 

 

#include<stdlib.h>  
#include<string.h>  
#include"qt.h"  
  
struct qt* qt(int i)  
{  
  size_t size = sizeof(i);  
  struct qt* v = (struct qt*) malloc(sizeof(struct qt) + size);  
  if (v != NULL)  
  {  
    v->size = size;  
    memcpy(v->data, &i, sizeof(i));  
  }  
  return v;  
}  
  
int qt_get(struct qt* v)  
{  
  int *p = NULL;  
  if (v == NULL)  
  {  
    return 0;  
  }  
  p = (int *) v->data;  
  return *p;  
}  
  
int qt_destroy(struct qt* v)  
{  
  free(v);
  return 0;
}  

编译

 

# gcc -c qt.c -o qt.o

生成静态库

# ar rc libqt.a qt.o

 

#include <stdio.h>  
#include "qt.h"

#import <Foundation/Foundation.h>

int main(int argc, char *argv[])
{
  int i = 1413;  
  struct qt* v = qt(i);  
  if (v == NULL)  
  {  
    return 1;  
  }  
  printf("qt: i=%d\n", qt_get(v));
  
  NSLog(@"qt: i=%d", qt_get(v));
  qt_destroy(v);  
  return 0;	
}

gcc -framework Foundation -L . libqt_test.m -o libqt_test -lqt

 

编写静态链接库

#include <stddef.h>  
  
#if ! defined(QT)  
#define QT  
struct qt  
{  
  size_t size;  
  char data[];  
};  
  
struct qt* qt(int i);  
  
int qt_get(struct qt* v);  
  
int qt_destroy(struct qt* v);  
#endif 

其实就是把上面的.c文件改为.m文件即可。

#include<stdlib.h>  
#include<string.h>  
#include"qt.h"  
  
struct qt* qt(int i)  
{  
  size_t size = sizeof(i);  
  struct qt* v = (struct qt*) malloc(sizeof(struct qt) + size);  
  if (v != NULL)  
  {  
    v->size = size;  
    memcpy(v->data, &i, sizeof(i));  
  }  
  return v;  
}  
  
int qt_get(struct qt* v)  
{  
  int *p = NULL;  
  if (v == NULL)  
  {  
    return 0;  
  }  
  p = (int *) v->data;  
  return *p;  
}  
  
int qt_destroy(struct qt* v)  
{  
  free(v);
  return 0;
}  

编译

 

# gcc -c qt.m -o qt.o

生成静态库

# ar rc libqt.a qt.o

 

#include <stdio.h>  
#include "qt.h"

#import <Foundation/Foundation.h>

int main(int argc, char *argv[])
{
  int i = 1413;  
  struct qt* v = qt(i);  
  if (v == NULL)  
  {  
    return 1;  
  }  
  printf("qt: i=%d\n", qt_get(v));
  
  NSLog(@"qt: i=%d", qt_get(v));
  qt_destroy(v);  
  return 0;	
}

gcc -framework Foundation -L . libqt_test.m -o libqt_test -lqt

 

编译

$ gcc -framework Foundation hello.m -o hello -v

Apple LLVM version 9.0.0 (clang-900.0.39.2)

Target: x86_64-apple-darwin16.7.0

Thread model: posix

InstalledDir: /Library/Developer/CommandLineTools/usr/bin

 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.12.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hello.m -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -target-linker-version 305 -v -dwarf-column-info -debugger-tuning=lldb -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/9.0.0 -fdebug-compilation-dir /root/objective-c -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fobjc-runtime=macosx-10.12.0 -fencode-extended-block-signature -fobjc-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/2l/yzjcl8j56693p3y40qcnr4zc0000gn/T/hello-313d89.o -x objective-c hello.m

clang -cc1 version 9.0.0 (clang-900.0.39.2) default target x86_64-apple-darwin16.7.0

#include "..." search starts here:

#include <...> search starts here:

 /usr/local/include

 /Library/Developer/CommandLineTools/usr/lib/clang/9.0.0/include

 /Library/Developer/CommandLineTools/usr/include

 /usr/include

 /System/Library/Frameworks (framework directory)

 /Library/Frameworks (framework directory)

End of search list.

 

 "/Library/Developer/CommandLineTools/usr/bin/ld" -demangle -lto_library /Library/Developer/CommandLineTools/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -macosx_version_min 10.12.0 -o hello -framework Foundation /var/folders/2l/yzjcl8j56693p3y40qcnr4zc0000gn/T/hello-313d89.o -lSystem /Library/Developer/CommandLineTools/usr/lib/clang/9.0.0/lib/darwin/libclang_rt.osx.a

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics