Slice 语言定义

文档中对于slice的定义

在这里,我们提供Slice语言。 Slice(Specification Language for Ice)是一种将对象接口与其实现分离的基本抽象机制。Slice在客户端和服务器之间建立一个描述应用程序使用的类型和对象接口的合同。该描述与实现语言无关,因此客户端是否以与服务器相同的语言编写并不重要。

即使尽管Slice是一个首字母缩略词,它的发音是一个音节,像a slice of bread

Slice定义是由编译器为特定的实现语言编译的。编译器将与语言无关的定义转换为特定语言的类型定义和api。开发人员使用这些类型和API来提供应用程序功能并与Ice进行交互,用于各种实现语言的翻译算法被称为语言映射。目前,Ice定义了C ++,Java,C#,Python,Objective-C,Ruby和PHP的语言映射。

因为Slice描述的是接口和类型(但不是实现),它是纯粹的声明性语言;不能在Slice中编写可执行的语句。

Slice定义侧重于对象接口,这些接口支持的操作以及可能由操作引发的异常。此外,Slice还提供了对象持久化的特性。这需要相当多的支持机制;特别是,大部分的Slice内容都涉及到数据类型的定义。这是因为只有在Slice中定义了类型,才能在客户端和服务器之间交换数据。您不能在客户端和服务器之间交换任意的C ++数据,因为它会破坏Ice的语言独立性。但是,您总是可以创建一个Slice类型的定义,它对应于您想要发送的c++数据,然后可以传输Slice类型。

Slice 语言的作用如图

文档原图

Slice 源文件 Slice Source Files

文件命名

包含Slice定义的文件必须以 .ice结尾。例如,clock.ice是一个有效的文件名。其他文件扩展被编译器拒绝。

对于不区分大小写的文件系统(如DOS),可以将文件扩展名写成大写或小写,因此Clock.ICE是合法的。对于区分大小写的文件系统(如Unix),Clock.ICE是非法的。(扩展必须是小写的。)

文件格式

Slice是一种自由格式的语言,因此你可以使用空格、横向和纵向制表符、换行符安排你的代码布局。Slice中语义和定义的布局没有关联。

Slice文件可以是ASCII文本文件,或者在每个文件的开头用字节顺序标记(BOM)使用utf - 8字符编码。但是,Slice标识符仅限于ASCII字母和数字;非ASCII字母只能出现在注释和字符串文字中。

预处理

Slice支持与c++相同的预处理指令,因此您可以使用诸如# include和宏定义之类的指令。但是,Slice许可证#只包含在文件开头的指令,在任何切片定义之前。

如果你使用# include指令,那么保护他们,以防止双重包含文件是一个好主意:

用#pragma也可以得到相同的结果

检测Ice 版本

在在Ice 3.5中,Slice编译器定义了预处理器宏__ICE_VERSION__,可以用来实现Ice版本的兼容

检测Slice编译器

在Ice 3.5中,每个Slice编译器定义它自己的宏,这样您就可以为某些语言映射定制您的Slice代码。下面的宏由各自的编译器定义:

例如 .NET开发人员可能会选择避免对结构成员使用默认值,因为默认值的存在会改变结构到类的结构的c#映射:

词法规则 Lexical Rules

注释(支持c和c++两种风格的注释)

关键字

Slice使用一些关键字,必须用小写字母拼写。例如,class和dictionary是关键字,必须这样拼写。这个小写规则有两个例外:Object和LocalObject是关键字,必须大写。

标识符

标识符以字母字符开头,后面跟着任意数量的字母字符或数字。在标识符中也允许有以下限制:

标识符不能以下划线开始或结束

标识符不能包含多个连续下划线

标识符get_account_name是合法的,但这些是非法的 _account、account_或get__account。

Slice标识符仅限于字母字符的ASCII范围,不能包含非英语字母,如Å。(支持非ascii标识符将使将Slice映射到缺少该特性支持的目标语言非常困难。)

大小写敏感

标识符是大小写不敏感的,但是必须保持拼写一致。例如TimeOfDay和TIMEOFDAY在同一个命名空间中是一样的。但是,Slice强制拼写一致。一旦你定义了一个标识符之后,你必须自始至终的拼写这个标识符的大小写,否则,编译器会认为这是非法的标识符。这条规则之所以存在,是因为这样就允许Slice可以映射到大小写敏感的语言也能映射到大小写不敏感的语言。

是关键字的标识符

你可以使用其他语言的关键字来定义Slice标示符,例如,switch可以用来作为Slice标识符,但是也是Java和 C plus plus 的关键字。Slice语言映射中针对每一种语言都定义了映射规则来处理这样的标识符。例如,Slice把switch映射为 C plus plus 的_cpp_stitch和Java的_switch。但不建议这样使用,您应该至少尝试避免常见的关键字。Slice标识符如self、import和while绝对不是一个好主意。

转义的标识符

可以使用Slice关键字作为标识符,通过使用反斜杠来预先确定关键字:(但也不推荐这样使用,应尽量避免)

保留的标识符

Slice将Ice以及以Ice开始的所有标识符作为保留的标识符。例如,Icecream将会被认为是非法的标识符。

同时,Slice还将以以下标识符为后缀的标识符视为保留的标识符:

Helper

Hodler

Prx

Ptr

保留它们,主要是为了防止在生成代码时发生冲突。

模块Modules

Slice提供模块来保持整体结构的条理性

模块是强制性的,所有定义必须在模块中 Modules are Mandatory

在全局范围内的定义是被禁止的,因为它们会导致一些实现语言(例如Python,它没有真正的全局作用域)的问题。

重启模块 Reopening Modules

模块可以重新开放:

重新打开的模块对于更大的项目是有用的:它们允许您在多个不同的源文件中分割一个模块的内容。这样做的好处是,当开发人员对模块的一部分进行更改时,只有依赖于更改部分的文件需要重新编译(而不是必须重新编译使用该模块的所有文件)。

模块的映射 Module Mapping

模块映射到每个编程语言中相应的范围构造。(例如,对于c++和c#,Slice模块映射到命名空间,而对于Java,它们映射到包。)这允许您使用适当的c++使用或Java导入声明,以避免在源代码中使用过多的标识符。

Ice 模块 The Ice Module

Ice运行时的api,除了少数无法用Ice表达的特定语言的调用,都是在Ice模块中定义的。换句话说,大部分的Ice API实际上表示为Slice定义。这样做的好处是,Slice定义就足以为所有受支持的语言定义Ice运行时间的API。然后,各自的语言映射规则确定每个实现语言的每个Ice API的确切形状。

基本数据类型 Basic Types

Slice中内置了一些基本数据类型

数据类型

所有基本类型(除了byte类型)在服务器和客户端之间传递时,数据类型都根据实际情况在变化。例如:一个long类型的值在从一台little-endian机器传递到bit-endian机器时会发生位变换。类似的,string在从EBCDIC发往ASCII时也是进行翻译的,也许string的字符的尺寸也发生了变化,因为不是所有的机器都使用8位的字符。实际上,这些变化对于程序员来说都是透明的,而且会严格按照需要来变化。

整数类形(integer types)

Slice提供了如下的整数类型:

short,16位

int,32位

long,64位

不过,这些类型在某些机器上会映射到更宽的原生类型。需要注意的是那些无符号类型Slice并没有提供。因为无符号类型影射到那些没有原生的无符号类型的语言相当困难,例如Java。

浮点数类型(floating-point types)

浮点数类型遵循IEEE的规范。如果一个实现语言么有支持IEEE的浮点数格式,Ice运行时会将浮点数值转换为原生浮点数表示。

字符串(strings)

Slice字符串使用Unicode字符集。唯一的不能出现在字符串中的字符就是零字符。

Slice没有null字符串的概念。这是因为null字符串很难映射到不直接支持null字符串概念的语言上,例如Python。不要设计依靠一个null字符串来表示“不在那里”的语义的接口。如果你需要表示可选的串,可以通过使用类,字符串的序列,或者一个空的字符串来表示null字符串。

布尔类型(booleans)

布尔类型的值只能由false和true。如果语言映射时有原生布尔类型,语言映射就会使用该类型。

Byte类型(bytes)

Slice定义byte是一个至少8位的,在地址空间中传递时保证不会发生变化的类型。保证不发生变化就允许交换二进制数据,而这些数据不会被篆改。其他的Slice类型都会在传递过程中会被改变表达形式。

自定义数据类型 User-Defined Types

枚举(Enumerations)

这个定义引入了一个名为水果的类型,它本身就是一种新的类型。Slice保证枚举器的值从左到右增长,默认情况下,第一个枚举器的值为0,后续枚举器的值顺序递增。

Slice枚举器符号进入封闭命名空间范围,因此以下是非法的:

下面的示例展示了如何从不同的范围引用枚举器

Slice不允许空的枚举。

自定义枚举器值 Custom Enumerator Values

Slice允许你为枚举器分配自定义值

自定义值必须是唯一的和非负的,并且可以引用整数类型的Slice常量。如果没有为枚举器指定自定义值,那么它的值就是大于前面的枚举器的值。在上面的例子中,橙色的值为8。

枚举值的最大值与int的最大值(2(31次方)- 1)相同。

Slice不需要将自定义枚举值声明为递增顺序:

但是注意,当声明顺序和枚举器的数值次序之间不一致时,比较操作的行为可能会因语言映射而有所不同。因此推荐在自定义枚举值时也按照递增顺序排列

结构(Structures)

Slice支持包含一个或多个任意类型的命名成员的结构,包括用户定义的复杂类型。例如:

结构中不能出现结构定义,例如下面的代码是错误的:

这条规则适用于一般情况:类型定义不能嵌套(除了用于支持嵌套的模块)。这条规则的原因是嵌套类型定义可能难以实现一些目标语言,即使是可实现的,极大地使范围解析规则复杂化。对于规范语言,例如Slice,嵌套的类型定义是不必要的——您可以始终将上面的定义写如下(这也是风格上的清洁):

您可以为具有以下类型的数据成员指定一个默认值:

An integral type (byte, short, int, long)

A floating point type (float or double)

string

bool

enum

序列(Sequeces)

序列是可变长度的元素集合

一个序列可以是空的——也就是说,它可以不包含任何元素,或者它可以将任何数量的元素都保存到平台的内存限制中。

序列可以包含本身序列的元素。这种安排允许你创建列表的列表:

序列用于建模各种集合,如向量、列表、队列、集合、包或树。(取决于应用程序来决定顺序是否重要;通过丢弃顺序,序列充当一个集合或包。)

使用序列来定义model中的可选字段。

字典(Dictionaries)

字典是一个从键类型到值类型的映射。

例如:

上面的定义创建了一个名为employeemap的字典,它达到了从employee编号到一个包含有employee详细信息的结构的映射。

字典key和value的允许类型

字典的关键类型不需要是整数类型。例如,我们可以用下面的定义来翻译一周的日子:

服务器实现将负责初始化该映射,并与键值对monday - montag、tuesday - dienstag等进行初始化。

字典的值类型可以是任何类型的。但是,字典的关键类型仅限于以下类型之一:

Integral types (byte, short, int, long, bool)

string

enum

Structures containing only data members of legal key types

其他复杂类型,如字典和浮点类型(float和double)不能用作键类型。复杂类型是不允许的,因为它们使字典的语言映射变得更加复杂,并且浮点类型是不允许的,因为跨机器边界的值的具象变化会导致定义不明确的等式语义。

常量 Constants and Literals

Slice 允许你用以下类型定义常量

An integral type (bool, byte, short, int, long)

A floating point type (float or double)

string

enum

布尔常量

boolean常量只能用true和false的关键词来初始化。(你不能用0和1来表示false和true。)

整形常量

整数常量可以用十进制、八进制或十六进制表示。

请注意,如果将byte解释为一个数字而不是一个位模式,您可能会得到不同语言的不同结果。例如,对于c++,byte映射到unsigned char,而对于Java,byte映射到byte,这是一个符号类型。

注意,后缀表示long且无符号的常量(l,L,u,U, used by C++)是非法的:

整数的值必须在其常量类型的范围内,如内置的基本类型表中所示;否则编译器将发出诊断。

浮点型常量

浮点常数使用 C++ 的语法,只是你不能使用 l 或 L 后缀以指示扩展的浮点常数;然而,f 和 F 则是合法的 (但被忽略)。

浮点常量必须在常量类型的范围内(float或double);否则,编译器会发出诊断。

字符型常量

字符串文本支持与c++相同的转义序列

请注意,Slice没有空字符串的概念

Null字符串根本不存在于Slice中,在Ice平台中的任何地方都不能作为一个字符串的合法值。这个决定的原因是,在许多编程语言中都不存在null字符串。

除了C和c++之外,许多语言使用字节数组作为内部字符串表示。在这种语言中,null字符串不存在(并且很难映射)。

常数表达式

常数定义也可以指另一个常数。对于两个常量来说,具有相同的Slice类型并不是必需的,但是现有常量的值必须与定义的常量类型一致

DEFAULT_SIZE常量是合法的,因为它具有与SIZE相同的类型,并且SHORT_SIZE是合法的,因为SIZE(500)的值在Slice short类型的范围内。但是,BYTE_SIZE是非法的,因为SIZE的值超出了byte类型的范围。

ICE的slice定义注意事项
1、源文件规则
1)、文件扩展名必须为.ice
2)、在使用#include来包含其他的ice定义文件时,只能使用<>,不能使用""。在使用路径包含时,使用linux风格的斜线,不能使用windows风格的反斜线
3)、每个slice定义文件中最好加上#ifndef的宏定义,防止文件的双重包含
4)、文件必须是utf-8编码的

2、词法规则
1)、slice文件支持c++的单行和多行注释
2)、slice定义中的关键字均为小写
3)、slice文件中关键字不能以下划线开始和结尾,当然这一规则也是可以打破的,在编译slice文件的时候使用“--underscore”的编译选项
4)、slice的关键字虽然是大小写敏感的,但是为了保证ice能够映射到非大小写敏感的系统,因此最好不要采用不同的大小写拼写规则来区分两个关键字,即你可以认为是非大小写敏感的。
5)、虽然说部分语言关键字不是slice的关键字,但是最好不要使用,因为slice的编译器会对这些语言相关的关键字进行特殊处理,从而带来代码可读性的降低
6)、如果以前定义的slice文件中标示符与新的ice版本规则冲突,可以使用反斜线"\"来表示关键字为一个普通的标示符
7)、slice定义文件中禁止标示符以“ice”开头。当然这一规则也是可以打破的,在编译slice文件的时候使用“--ice”的编译选项
8)、slice定义文件中禁止标示符以"Helper"、“Holder”、“Prx”、“Ptr”结尾。

3、名字空间
1)、在全局的名字空间中只允许出现名字空间的定义,即slice文件定义的最顶层必须是名字空间定义Moudle XXX
2)、可以再不同的文件中使用相同的名字空间,就像多个c++文件中定义名字空间的不同类型一样

4、数据类型
1)、slice提供的基本数据类型包括:bool、byte、short、int、long、float、double、string。扩展数据类型包括:enum、struct、sequence、dictionary。
2)、特别注意slice不提供所谓的无符号类型,因为在某些程序设计语言中,就不提供native的unsigned类型,因此slice无法做无符号类型的语言映射
3)、slice的string字符串必须使用unicode字符集,同时不能包含0的。如果需要使用包含其他字符集或者0的串,可以考虑使用byte结构来存储
4)、布尔值bool的取值只能是flase或者true
5)、byte类型在slice的语言映射中会始终保证是8字节的,同时在网络传输过程中也不会受网络和本地字节序的影响
6)、slice的enum类型是不允许用户来制定枚举成员的取值的,但是slice能够确保枚举类型中后面的成员取值大于前面的成员取值,因此枚举成员是可以做大小比较的。slice不允许定义空的枚举类型,即枚举类型中必须有成员定义
7)、slice中struct不支持类型的嵌套定义,即不允许在一个struct数据类型中再次定义一个struct的数据类型
8)、结构中的基本数据类型和枚举类型支持在定义的时候指定默认值
9)、需要使用变长的数据集合时,可以使用sequence来定义。sequence的一种特殊用法是用来标示可选值,因为sequence数据成员可以是空的数据集合。为了表示一个空的数据集合,我们一般这样来定义:sequence<XXX> TypeOpt; TypeOpt Parameter; Opt的后缀一般迎来标示该序列集合是允许为空的可选集合或者参数
10)、需要使用类似map的类型映射结构时,可以使用dictionary来定义。但是dictionary的key字段是有约束的,只能是如下类型:byte、short、int、long、bool、string、enum、数据成员为整形或者字符串的结构。
11)、slice常量定义允许的类型:整形、浮点、字符串、枚举。注意整型常量的取值不能带长度标示(l、L、u、U);浮点和字符串常量的语法定义基本同c++;常量取值时需要设置允许范围内的值,否则slice编译时会提示错误;常量定义取值时是可以引用其他常量的,只要确保其取值范围是合法的。

5、接口定义
1)、接口操作必须包含如下信息:返回值、接口名称、输入参数类型和名称(如果存在)、输出参数类型和名称(如果存在)。
2)、接口操作在参数排版上要求输出参数必须在输入参数的后面,并且不支持输入输出参数,即参数的数据传递方向是单一的。不支持默认值参数
3)、同一个接口内部不允许操作重名的。即不支持接口操作的重载
4)、如果某一个操作不会改变其接口对象的状态,请将其表示为nonmutating。即类似c++的常量函数(函数名后加const)。这样标示的好处是ice的运行环境能够在函数调用过程发生底层的一些错误情况下更积极的重新尝试,保证系统有更好的容错性能。
5)、如果一个操作在一个接口对象上连续执行两次与一次的效果是一样的,那么为了能够让系统有更好的容错性能,请将接口表示为idempotent。从这个角度去理解,那么nonmutating操作也是idempotent的。
6)、接口可以传递代理类型,即类似如c++的指针类型。这样做的一个好处是客户端能够传递一个带操作的数据结构给服务器端,这样客户端和服务器端能够传递除了数据之外的操作实现。需要做的事情仅仅是在slice中定义一个接口的指针,注意是“接口”。
7)、接口是可以继承的,当然包含多重继承。但是需要注意的一点是,多重继承的多个基类中不能包含相同名称的操作。
8)、始终的有一个观念就是,所有接口都共有同一个基类Object,但是你不能显示的从Object继承,这是slice隐私为大家实现的。注意Object的O大写了。这是关键字中的一个特例

6、异常处理

1)、异常的定义有点类似结构,可以在其定义任何数据类型。但是和结构不同的是异常可以不包含任何数据成员
2)、异常定义时也支持和常量一样的默认值定义语法规则。即基本数据类型支持在定义的时候制定默认值
3)、可以设置某一个接口操作会抛出特定类型的异常,当然在该接口操作实现过程中也只能抛出申明的异常,否则ice的会报运行时错误
4)、为了能够更好的保证系统的向下兼容性,最好在系统初始定义时就设置好操作的异常(即使初始实现时是没有异常抛出的)。
5)、异常是支持继承的。即可以向下扩展异常的信息。但是不支持多重继承。可以再申明抛出基类异常的操作中抛出子类异常
6)、服务器抛送给客户端的异常有如下几种情况:用户异常、ObjectNotExistException、FacetNotExistException、OperationNotExistException、UnknownUserException(操作的实现抛出了一个未声明的异常)、UnknownLocalException(系统未捕获操作申明的异常)、UnknownException(语言系统的异常)

7、类
1)、类在数据成员定义上与结构相同、在操作定义上与接口类似。他是一个两中类型的混合物。类相比结构支持继承扩展、支持多态、支持自引用,相比接口有具备数据属性
2)、为了能够具备更好的性能,如果struct就能够完成的事情,不要大费周章的来弄个class来搞
3)、一定要区分类的自引用和接口的自引用的差异化。类的自引用时确实的值存在,但是接口的自引用时指针存在,即不是值域空间。因此在一些操作中,需要从时间和空间的角度来考虑是采用值引用还是指针引用。
4)、在接口或者类的操作中如果参数是一个类,那么一定要注意,在客户端和服务器端的交互中仅仅传递了发送方的类成员,其操作的行为并没有进行传递,因此不能确保其操作的行为在客户端和服务器端的解释是一样的。为了能够在客户端和服务器端传递操作,最保险的做法是使用接口来代替类进行操作传递。当然如果你能保证客户端和服务器端的操作行为完全一致,用类来做不失为一种好的做法,因为在操作的执行上由于是在本地地址空间,而不会产生类似接口代理的RPC调用产生更重的调用开销。
5)、类可是实现一个或多个接口,在这种场景下,一个类实例的接口调用,一定要区分该操作时从接口继承下来的,还是类扩展的。这样才知道其调用实现时远程的还是本地的。
6)、类和接口一样,不能重载操作。在继承基类或者实现接口时,不能扩展和基类、实现接口相同的成员变量或者操作名称
7)、一定要注意,如果使用类来代替接口传递代理(即指针)给接收方,那么仅仅是传递了一个代理,你只能理解是一个接口,而无法通过代理访问类的数据成员。
8)、在相互引用的类和接口定义中,前置声明就成为了一种不得不用的手段。

8、其他
1)、每个扩展的类和接口都有一个类型ID,一般而言,类型ID 起头是全局作用域(::),然后在后面附加包含该类型的各嵌套模块的名字,最后再以该类型自身的名字结束
2)、Object类提供了一些基本的操作:ice_ping、ice_isA、ice_id、ice_ids

ICE之Slice语言相关推荐

  1. 第三章 学习ICE 3.0--Slice语言

    Slice语言 首先,请大家读ICE中文手册中的Slice语言一章. 这一部分除了model(模块),在 ICE 1.3中文手册中都有描述 图 2.1. ice网络编程示意图(服务器端和客户端采用同种 ...

  2. ice库c语言例子,很不多的ICE架构入门学习例子

    虽然使用传统的SOCKET编程,我们可以更为清楚程序的性能,能够更直接的操控SOCKET的设置,比如发送超时时间,接受BUFFER的大小,以及进行自己的协议加密.但是由于其调试成本较高,且不易于分布式 ...

  3. 跨语言RPC框架Hessian、Thrift、Protocol Buffer之间的选择

    为什么80%的码农都做不了架构师?>>>    总结在几者之间选择的考量: 1. 如果你不需要很多语言相互调用, 希望保持清晰的java接口代码(无任何业务不相关的接口继承和方法,属 ...

  4. PHP中间件ICE,ICE的安装配置,ICE常见编译和运行(异常)错误(自测Php版本安装部分,因为php版本跟ice版本不一样失败)

    ICE(Internet Communications Engine)是Zeroc提供的一款高性能的中间件.使用ICE能使得php(或c++,java,python)与java,c++,.net,py ...

  5. ICE专题:ICE简介

    ICE(Internet Communications Engine)是一个为现实中程序员而写的中间件平台.作为一个高性能的互联网通信平台,ICE包含了很多分层的服务和插件(Plug-ins),并且简 ...

  6. zeroc ice的概念、组成与服务

    基本概念: •服务器/客户端(server/client):这个的定义与一般的定义相同,主动的一方被认为是client . •ICE对象:跟OOP中的对象类似,不同之处在于,在分布式的环境中,同一个I ...

  7. ZeroC Ice 暂记

    摘自: http://weibo.com/p/1001603869896789339575 原文地址: http://www.oschina.net/question/865233_242146 吴治 ...

  8. 【ICE学习】IceBox管理服务(C#)

    [前提条件]: 已安装VS2012和ICE3.5.1,ICE安装包:https://download.csdn.net/download/xmzmqx/12928570 安装搭建环境比较简单,请自行百 ...

  9. PHP中间件--ICE

    ICE(Internet Communications Engine)是Zeroc提供的一款高性能的中间件.使用ICE能使得php(或c++,java,python)与java,c++,.net,py ...

最新文章

  1. 刘文峰:让科技成就艺术创意
  2. 前端学习(3031):vue+element今日头条管理-暂时当前登录用户信息
  3. pwn和逆向的区别_Pwn之简单patch
  4. Spring Boot2 整合 MyBatis 多数据源
  5. pymongo查询列表元素_Python数据类型之列表list
  6. 理解URL以及如何区分相对URL和绝对URL
  7. sublime添加ctags实现代码跳转
  8. 机器学习:过拟合问题与其正则化解决
  9. Java IO流使用过程中乱码问题总结
  10. apache2.4.37无法解析php,编译安装apache2.4.37(Server version: Apache/2.4.37 )
  11. EAS中没有的核算项目新增
  12. iOS百度地图路径规划功能(对官网文档的理解)
  13. python求梅森尼数_梅森尼数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
  14. 我为什么选择鲸交所WhaleEx?
  15. 项目管理工具——项目开发者工具
  16. JAVA中的前后端交互
  17. SpringMVC——过滤器
  18. anaconda下载python的库_Anaconda下载及安装及查看安装的Python库用法
  19. SATA revision 3.2 specification
  20. BT开源项目Snark源码分析

热门文章

  1. GPU初始化和启动流程(r600)
  2. 机器学习——支持向量机算法
  3. Flutter绘制指南05-图形的路径添加
  4. 网络:分布式和网络的区别
  5. 安装php_soap.dll,php如何安装soap扩展
  6. 大数据学习笔记—大数据概论
  7. 靠智慧教育“飞升”,科大讯飞前路漫漫
  8. [导入]理解C#值类型与引用类型
  9. 作为外包,你冤枉了吗?| 程序员有话说
  10. 【蓝桥杯摆烂篇】蓝桥模拟赛【摆烂day3】