Blocks 的实现

Block 的实现是面试中高频出现的问题,背后的原因我想是希望借此考察面试者对 Block 的掌握程度,在日后的工作中能够用好它;同时能从侧面反映面试者有没有深入钻研技术,以及独立思考能力如何,可谓一举多得。

下面我们就来看看 ObjC 中的 Blocks 是如何实现。Clang 的 -rewrite-objc 选项可以将含有 Block 语法的源代码转换为 C++,说是 C++,其实也仅使用了 struct 结构,其本质是 C 语言。

下面我们先转换一个简单的文件试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#import <Foundation/Foundation.h>

int main(int argc, char ** argv)
{
    @autoreleasepool {
        void (^blk)(void) = ^{
            printf("Block\n");
        };

        blk();
    }

    return 0;
}

// 使用命令:
$ clang -fobjc-arc -ObjC -rewrite-objc -mios-version-min=6.0.0 -fobjc-runtime=ios-6.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk -arch arm64 block-essense.m  -o block-essense-in-c.c

//限于篇幅,省略不相关的部分,结果如下:
struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

            printf("Block\n");
        }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, char ** argv)
{
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));

        ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
    }

    return 0;
}
继续阅读

OpenLDAP 学习笔记

最近业余时间在自学 Java,接触到 JNDI,继而牵扯出 LDAP。在倒腾过程中感觉是个复杂的主题,决定做个简要的笔记,梳理下思路,也方便日后忘记时容易拾起。

OpenLDAP 是 LDAP 协议的一个开源实现。LDAP 服务器本质上是一个为只读访问而优化的非关系型数据库。它主要用做地址簿查询(如 email 客户端)或对各种服务访问做后台认证以及用户数据权限管控。(例如,访问 Samba 时,LDAP 可以起到域控制器的作用;或者 Linux 系统认证 时代替 /etc/passwd 的作用。)

以 slap 开头的命令如: slapacl, slapadd 等是服务端工具;以 ldap 开头的命令如: ldapadd, ldapcompare 等是客户端命令工具。

安装

Mac 内置了 OpenLDAP 软件包,所以可以直接使用。

配置

服务端

服务端支持两种配置方法:动态运行时配置引擎和老式的 slapd.conf 文件。这里介绍通过老式的 slapd.conf 文件转换成动态运行时配置引擎来配置服务器的方法。

服务器的配置文件位于 /etc/openldap/slapd.conf。在 Mac 上第一次配置时该文件还不存在,但有一个 slapd.conf.default 文件,从文件名可知,这应该是一个默认配置文件,所以我们可以在它基础上来配置。

1
$ sudo cp /etc/openldap/slapd.conf.default /etc/openldap/slapd.conf

需要编辑后缀和 rootdn。典型的后缀通常是你所用的域名,但这并非强制要求,而是依赖于你如何使用你的目录。下例中以 tenneshop 做为域名,tld 为 com,rootdn 则是 LDAP 管理员的名字(这里用 Manager)。

继续阅读

Web 开发问题汇总(三)

1.How to send email in java?

A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class SendEmail {

   public static void main(String [] args) {
      // Recipient's email ID needs to be mentioned.
      String to = "abcd@gmail.com";

      // Sender's email ID needs to be mentioned
      String from = "web@gmail.com";

      // Assuming you are sending email from localhost
      String host = "localhost";

      // Get system properties
      Properties properties = System.getProperties();

      // Setup mail server
      properties.setProperty("mail.smtp.host", host);

      // Get the default Session object.
      Session session = Session.getDefaultInstance(properties);

      try {
         // Create a default MimeMessage object.
         MimeMessage message = new MimeMessage(session);

         // Set From: header field of the header.
         message.setFrom(new InternetAddress(from));

         // Set To: header field of the header.
         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

         // Set Subject: header field
         message.setSubject("This is the Subject Line!");

         // Now set the actual message
         message.setText("This is actual message");

         // Send message
         Transport.send(message);
         System.out.println("Sent message successfully....");
      } catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}

Reference:Java - Sending Email
Send email using java

继续阅读