Chuẩn gọi hàm phiên bản 1 cho các hà mC

Một phần của tài liệu (LUẬN VĂN THẠC SĨ) Tìm kiếm nhạc số dựa trên chuỗi đặc trưng âm thanh (Trang 46 - 50)

2.3. Các hàm mở rộng trong ngôn ngữ C

2.3.4. Chuẩn gọi hàm phiên bản 1 cho các hà mC

Phương pháp gọi hàm này dựa vào các marco ựể bỏ ựi tắnh phức tạp khi truyền ựối số và kết quả trả về. Khai báo C của một hàm theo chuẩn 1 luôn luôn là:

Datum funcname(PG_FUNCTION_ARGS)

Thêm vào ựó, lời gọi marco:

PG_FUNCTION_INFO_V1(funcname);

phải xuất hiện trong cùng một file chương trình (thông thường marco này ựược ựặt ngay trước ựịnh nghĩa của hàm).

đối với chuẩn 1, các ựối số nhận ựược bằng cách sử dụng marco

PG_GETARG_xxx() tương ứng với kiểu dữ liệu của ựối số và kết quả nhận ựược bởi marco PG_RETURN_xxx() tương ứng với kiểu trả về.

Sau ựây là ựịnh nghĩa hàm ựược ựưa ra ở trên nhưng viết theo chuẩn 1:

#include "postgres.h" #include <string.h>

#include "fmgr.h" /* by value */

PG_FUNCTION_INFO_V1(add_one); Datum add_one(PG_FUNCTION_ARGS) {

int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg + 1); }

/* b reference, fixed length */

PG_FUNCTION_INFO_V1(add_one_float8); Datum add_one_float8(PG_FUNCTION_ARGS) {

/* The macros for FLOAT8 hide its pass-by-reference nature. */ float8 arg = PG_GETARG_FLOAT8(0);

PG_RETURN_FLOAT8(arg + 1.0); }

PG_FUNCTION_INFO_V1(makepoint); Datum makepoint(PG_FUNCTION_ARGS) {

/* Here, the pass-by-reference nature of Point is not hidden. */ Point *pointx = PG_GETARG_POINT_P(0);

Point *pointy = PG_GETARG_POINT_P(1); Point *new_point = (Point *) palloc(sizeof(Point)); new_point->x = pointx->x;

new_point->y = pointy->y;

}

/* by reference, variable length */ PG_FUNCTION_INFO_V1(copytext); Datum copytext(PG_FUNCTION_ARGS) {

text *t = PG_GETARG_TEXT_P(0);

// VARSIZE is the total size of the struct in bytes. text *new_t = (text *) palloc(VARSIZE(t)); VARATT_SIZEP(new_t) = VARSIZE(t);

// VARDATA is a pointer to the data region of the struct. memcpy((void *) VARDATA(new_t), /* destination */

(void *) VARDATA(t), /* source */

VARSIZE(t)-VARHDRSZ); /* how many bytes */ PG_RETURN_TEXT_P(new_t);

}

PG_FUNCTION_INFO_V1(concat_text); Datum concat_text(PG_FUNCTION_ARGS) {

text *arg1 = PG_GETARG_TEXT_P(0); text *arg2 = PG_GETARG_TEXT_P(1);

int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) Ờ VARHDRSZ;

text *new_text = (text *) palloc(new_text_size); VARATT_SIZEP(new_text) = new_text_size;

memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1)- VARHDRSZ);

memcpy(VARDATA(new_text) + (VARSIZE(arg1)-VARHDRSZ), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ);

PG_RETURN_TEXT_P(new_text); }

Câu lệnh tạo hàm cho các hàm ựược viết theo chuẩn 1 cũng tương tự như trong chuẩn 0.

Mới nhìn qua, quy tắc viết hàm theo chuẩn 1 có vẻ như không rõ ràng. Tuy nhiên, phương pháp này mang lại nhiều tiện ắch bởi các marco giúp ẩn ựi các thông tin không cần thiết. Có thể dẫn chứng bằng dòng mã add_one_float8 khi chúng ta không cần phải quan tâm là float8 có phải là kiểu truyền bởi tham chiếu hay không. Một vắ dụ khác là marco GETARG ựược sử dụng cho các kiểu dữ liệu có ựộ dài thay ựổi cho phép nhận ựối số với các giá trị ựặc biệt.

Một trong những cải tiến lớn nhất của chuẩn 1 so với chuẩn 0 là nó cho phép xử lý hiệu quả khi giá trị nhập vào và kết quả trả về có giá trị null. Marco

PG_ARGISNULL(n) giúp cho việc kiểm tra xem liệu rằng giá trị nhập có giá trị null không (tất nhiên việc kiểm tra này chỉ thực sự cần thiết khi hàm không ựược môt tả là ỘstrictỢ). đối với marco PG_GETARG_xxx(), danh sách ựối số ựược ựánh thứ tự từ 0 và nó chỉ ựược thực hiện nếu không có ựối số nào mang giá trị null. để nhận ựược giá trị trả về là null, người ta thực hiện marco

PG_RETURN_NULL(); ựối với cả hai loại hàm ỘstrictỢ và ỘnonstrictỢ.

Một trong những tùy chọn ựược cung cấp trong chuẩn viết hàm mới này nằm trong hai thay ựổi của marco PG_GETARG_xxx(). Thay ựổi thứ nhất là marco

PG_GETARG_xxx_COPY() sẽ trả về một bản sao của ựối số ựể ựảm bảo an toàn khi thực hiện việc ghi giá trị bởi vì các marco thông thường ựôi lúc trả về kết quả là một con trỏ tới giá trị ựược lưu trữ trong một bảng mà chúng ta không ựược phép thay ựổi giá trị của nó. Thay ựổi thứ hai nằm ở marco nhận ba ựối số

ựịnh là 3). đối số thứ hai và thứ ba là ựịa chỉ ựầu tiên (offset) và ựội dài phân ựoạn (segment) ựược trả về. Các offset ựược tắnh từ 0 và nếu ựộ dài là âm, toàn bộ phần còn lại của giá trị sẽ ựược trả về. Marco này giúp cho việc truy cập ựược hiệu quả tới phân ựoạn ựoạn khác nhau của một giá trị lớn có kiểu lưu trữ là ỘexternalỢ.

Cuối cùng, các hàm theo chuẩn 1 có thể trả về kết quả là tập hợp, thực thi trigger hay ựiều khiển lời gọi các ngôn ngữ thủ tục (procedural-language). Chuẩn 1 cũng có tắnh khả chuyển cao hơn chuẩn 0 bởi vì nó không phá vỡ các giao thức gọi hàm trong chuẩn C.

Một phần của tài liệu (LUẬN VĂN THẠC SĨ) Tìm kiếm nhạc số dựa trên chuỗi đặc trưng âm thanh (Trang 46 - 50)

Tải bản đầy đủ (PDF)

(67 trang)