Tải bản đầy đủ (.doc) (36 trang)

quá trình ánh xạ (mapping) từ ngôn ngữ đặc tả sang ngôn ngữ cài đặt.doc.DOC

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (304.71 KB, 36 trang )

Lờ i n ó i đầ u
Ngày nay cùng với việc phát triển của mạng máy tính việc viết một ứng
dụng trên một máy đơn cục bộ không còn đợc a chuộng và thích hợp nữa . Các
chơng trình và ứng dụng hiện đại phải tích hợp và triệu gọi lẫn nhau trên mạng
Intranet (mạng cục bộ), mạng Internet (mạng toàn cầu).
Tuy nhiên một vấn đề nảy sinh ra , điểm bất đồng giữa các ngôn ngữ lập
trình . Các đối tợng thiết kế bằng ngôn ngữ nào thì sau khi biên dịch ra dạng nhị
phân (binary) chỉ có mã lệnh tơng ứng với ngôn ngữ đó mới có khả năng truy
xuất đợc đối tợng . Đối tợng C++ không dễ gì truy xuất đợc từ mã lệnh Delphi
hay Visual Basic một cách tự nhiên . (Mặc dù có một số kĩ thuật nh sử dụng th
viện liên kết động DLL nhng đó không phải là các giải pháp toàn diện ).
Các nhà lập trình luôn mong muốn tìm đợc một tiếng nói chung cho tất cả
các ngôn ngữ lập trình hiện có . Và thế là CORBA ra đời .
CORBA ( Common Object Request Broker Achitecture) - tạm dịch là
Kiến trúc môi giới gọi các đối tợng thông dụng . CORBA đợc hình thành từ
một tổ chức nghiên cứu quốc tế OMG (Object Management Group ) với sự hợp
tác của hơn 800 công ty . Tham vọng của OMG là đa ra cách để các đối tợng
viết bằng những ngôn ngữ khác nhau có thể triệu gọi lẫn nhau theo mô hình đối
tợng phân tán .
CORBA không phải là ngôn ngữ lập trình nh C++ hay Java . CORBA là
một ngôn ngữ đặc tả (description language) .
Sau đây sẽ trình bày quá trình ánh xạ (mapping) từ ngôn ngữ đặc tả sang
ngôn ngữ cài đặt
- 1 -
I. ánh xạ từ IDL sang C++
1. Giới thiệu:
ánh xạ IDL sang C++ phải thoã mãn các yêu cầu sau :
- ánh xạ phải có tính trực quan và dễ sử dụng
- phải bảo tồn ngôn ngữ chung của C++ và phải gần giống với C++ th-
ờng
- phải an toàn về kiểu


- sử dụng có hiệu quả chu kỳ của CPU và bộ nhớ
- thực hiện trên các cấu trúc của bộ nhớ đoạn và bộ nhớ vật lý
- phải đợc hớng nội sao cho nó có thể dùng trong môi trờng phân luồng
- ánh xạ phải bảo toàn tính che giấu cục bộ (tính trong suốt)
Việc ánh xạ sang C++ phức tạp và rộng lớn nhng không phải quá khó. Thứ
nhất, ánh xạ là thuận tiện ví dụ bạn hiểu rõ về cách tổ chức và quản lý bộ
nhớ của kiểu String, và các luật quản lý đối với kiểu dữ liệu Variable-
length, thứ hai, việc ánh xạ là an toàn, không yêu cầu sắc thái và bắt lỗi dễ
dàng trong lúc biên dịch
Thứ 3, sự ánh xạ này là dễ nhớ mặc dù lớp có nhiều hàm thành viên, nhng
bạn chỉ cần gọi một số hàm chính, còn một số hàm khác tồn tại mặc định
để cung cấp các chuyển đổi tham số truyền và không cần phải gọi rõ ràng
2. ánh xạ cho tên:
Cỏc tờn ca IDL c bo ton khi ỏnh x sang C++. minh ho cho
iu ny ta xột vớ d sau:
- Trong IDL:
enum color {red, green, blue};
- Khi ỏnh x sang C++:
enum color {red, green, blue};
Cỏc ỏnh x sang C++ cng bo ton cỏc toỏn t phm vi. Vớ d nu nh
trong IDL toỏn t phm vi Outer :: Inner l hp l thỡ khi ỏnh x sang C+
+ nú cng vn l Outer :: Inner.
Mt vn phỏt sinh khi trong IDL ta dựng tờn trựng vi t khoỏ trựng
vi cỏc t khoỏ ca C++:
Vớ d nh ngha sau l hon ton hp l trong IDL:
Enum class {if, this, while, case };
nhng khi ỏnh x sang C++ thỡ nú s t ng c thờm vo tin t:
_cxx_. Vỡ vy nú s cú dng nh sau:
enum _cxx_class { _cxx_if, _cxx_this, _cxx_while, _cxx_case };
- 2 -

các tiền tố này làm cho các câu lệnh trở nên khó đọc, do vậy tốt nhất là ta
nên tránh dùng chúng.
Bây giờ chúng ta sẽ đi xét chi tiết vào từng kiểu dữ liệu một
3. Ánh xạ các kiểu dữ liệu cơ bản
Các kiểu dữ liệu cơ bản được ánh xạ sang C++ được mô tả ở bảng sau:
OMG IDL C++ C++ Out Type
short CORBA::Short CORBA::Short_out
long CORBA::Long CORBA::Long_out
unsigned short CORBA::UShort CORBA::UShort_out
unsigned long CORBA::ULong CORBA::ULong_out
float CORBA::Float CORBA::Float_out
double CORBA::Double CORBA::Double_out
char CORBA::Char CORBA::Char_out
boolean CORBA::Boolean CORBA::Boolean_out
octet CORBA::Octet CORBA::Octet_out
4. Các kiểu dữ liệu phức:
Các kiểu dữ liệu phức ở trong IDL được ánh xạ sang C++ như sau:
OMG IDL C++
Object CORBA::Object_ptr
struct C++ struct
union C++ class
enum C++ enum
string char *
Sequence C++ class
array C++ array
a>. String
Một chuỗi trong IDL được ánh xạ sang C++ là char *. Cả chuỗi giới hạn
và chuỗi không giới hạn độ dài thì đều được ánh xạ sang C++ là char *.
Các chuỗi CORBA trong C++ được kết thúc bởi con trỏ NULL. Nếu một
chuỗi mà có chứa một kiểu tự định nghĩa khác, ví dụ như kiểu struct, thì

nó được ánh xạ sang kiểu C ORBA::String_v ar. Điều này đảm bảo rằng
- 3 -
mỗi thành phần trong struct được quản lý bởi chính bộ nhớ của nó. Các
chuỗi phải được cấp phát và ngừng cấp phát bằng việc sử dụng các hàm
thành phần sau trong lớp CORBA:
• string_alloc // hàm cấp phát
• string_dup
• string_free // hàm huỷ
Chú ý: hàm string_alloc cấp phát vùng nhớ có độ dài len+1 vì nó còn chứa
một ký tự null
b>.Enum
Các kiểu enum trong IDL được ánh xạ sang một kiểu enum trong C++
// IDL
module INVENT
{
enum Reply {ACCEPT, REFUSE};
}
// C++
class INVENT
{
. . .
enum Reply {ACCEPT, REFUSE};
};
Tham chiếu đến các thành phần như sau là hợp lệ:
INVENT::Reply accept_reply;
accept_reply = INVENT::ACCEPT;
c> .Struct
Các kiểu struct trong IDL được ánh xạ sang các kiểu struct trong C++.
Chúng ta cùng xem xét các cấu trúc có chiều dài cố định với các cấu trúc
có chiều dài thay đổi:

// IDL
module INVENT
{
// Chiều dài cố định
struct Date
{
long year;
- 4 -
long month;
long day;
};
// Chiều dài thay đổi
struct Address
{
string aptNum;
string streetName;
string city;
string state;
string zipCode;
};
};
// C++
class INVENT
{
struct Date
{
CORBA::Long year;
CORBA::Long month;
CORBA::Long day;
};

struct Address
{
CORBA::String_var aptNum;
CORBA::String_var streetName;
CORBA::String_var city;
CORBA::String_var state;
CORBA::String_var zipCode;
Address &operator=(const Address &_obj);
};
};
Đối với các kiểu dữ liệu cơ bản trong các thành phần của struct được ánh xạ
sang các kiểu tương ứng trong C++. Còn các kiểu dữ liệu như: tham chiếu đối
tượng, các tham chiếu giả đối tượng, các chuối thì được ánh xạ các lớp _var
tương ứng:
• CORBA::string_var
• CORBA::object_var
d> Union
- 5 -
Một kiểu Union trong IDL được ánh xạ sang một lớp trong C++. Lớp
này chứa:
• Các hàm tạo lập (Constructors)
• Các hàm huỷ (Destructors)
• Các toán tử gán
• Các thay đổi cho các giá trị của union
• Các bộ truy nhập cho các giá trị của union.
Ví dụ:
// IDL
union OrderItem switch (long)
{
case 1: itemStruct itemInfo;

case 2: orderStruct orderInfo;
default: ID idInfo;
};
// C++
class OrderItem
{
public:
OrderItem();
OrderItem(const OrderItem &);
~OrderItem();
OrderItem &operator=(const OrderItem&);
void _d (CORBA::Long);
CORBA::Long _d () const;
void itemInfo (const itemStruct &);
const itemStruct & itemInfo () const;
itemStruct & itemInfo ();
void orderInfo (const orderStruct &);
const orderStruct & orderInfo () const;
orderStruct & orderInfo ();
void idInfo (ID);
ID idInfo () const;
. . .
};
- 6 -
e> Các định nghĩa kiểu
Các định nghĩa kiểu trong IDL được ánh xạ trực tiếp sang các định nghĩa
kiểu của C++. Nếu định nghĩa kiểu IDL gốc được ánh xạ sang một vài
kiểu của C++ thì trình biên dịch của IDL sẽ sinh ra các bí danh tương ứng
cho mỗi kiểu trong C++.
// IDL

typedef octet example_octet;
typedef enum enum_values {
first,
second,
third
} enum_example;
// Kết quả trong C++
typedef octet example_octet;
enum enum_values {
first,
second,
third
};
typedef enum_values enum_example; // bí danh được tạo ra
f> Modules
Một module của IDL nên được ánh xạ sang một namespace của C++ với
tên tương tự
// IDL
module ABC
{
// Definitions
...
};
...
// Kết quả trong C++
class ABC
{
// Definitions
...
};

g> Sequences
- 7 -
Các sequences của IDL cả giưói hạn hay không giới hạn đều được ánh xạ
sang class của C++.
Chú ý: Khi chiều dài của sequence không giới hạn vượt quá chiều dài cực
đại thì C++ sẽ cấp phát trong suốt một buffer lớn hơn, nó sẽ copy buffer cũ
vào buffer mới và giải phong bộ nhớ khỏi buffer cũ. Tuy nhiên, nó sẽ
không thực hiện giải phóng bất kỳ bộ nhớ nào chưa bao giờ được dùng đến
nếu chiều dài cực đại giảm.
Xét ví dụ sau: ánh xạ một sequence không giới hạn (unbounded)của IDL
sang C++
// IDL
typedef sequence<long> LongSeq;
...
// Results in the generation of this C++ code
class LongSeq
{
public:
LongSeq(CORBA::ULong max=0);
LongSeq(CORBA::ULong max=0, CORBA::ULong length,
CORBA::Long *data, CORBA::Boolean release = 0);
LongSeq(const LongSeq&);
~LongSeq();
LongSeq& operator=(const LongSeq&);
CORBA::ULong maximum() const;
void length(CORBA::ULong len);
CORBA::ULong length() const;
const CORBA::ULong& operator[](CORBA::ULong index) const;
...
static LongSeq *_duplicate(LongSeq* ptr);

static void _release(LongSeq *ptr);
static CORBA::Long *allocbuf(CORBA::ULong nelems);
static void freebuf(CORBA::Long *data);
private:
CORBA::Long *_contents;
CORBA::ULong _count;
CORBA::ULong _num_allocated:
CORBA::Boolean _release_flag;
CORBA::Long _ref_count;
};
Ý nghĩa của các hàm được môt tả ở bảng sau:
- 8 -
Phương thức Mô tả
LongSeq(CORBA::ULong
max=0)
bộ tạo lập cho một sequence không giới hạn chiếm một chiều dài
cực đại như một tham số. Các sequence giới hạn thì có một chiều
dài cực đại xác định.
LongSeq(CORBA::ULong
max=0,
CORBA::ULong length,
CORBA::Long *data,
CORBA::Boolean
release=0)
Constructor này cho phép bạn đặt một chiều dài cực đại, chiều dài
hiện tại, một con trỏ tới bộ đệm dữ liệu kết hợp và một cờ giải
phóng.Nếu cờ giải phóng khác 0, ISB về C++ sẽ giải bộ nhớ kết
hợp với bộ đẹm dữ liệu khi tăng kích thước của sequence. Nếu cờ
giải phóng bằng 0 thì bộ nhớ của bộ dệm dữ liệu cũ không được
giải phóng. Sequence giới hạn có tất cả các thông số này trừ max.

LongSeq(const LongSeq&)Bộ tạo lập sao chép thực hiện sao chép sâu đối tượng nguồn.
~LongSeq(); Destructor giải phóng tất cả bộ nhớ của chính sequence nếu cờ giải
phóng (release flag) có giá trị khác không khi được tạo lập.
Operator=(const
LongSeq&j)
Toán tử gán thực hiện một sự ao chép sâu, giải phóng việc lưu trữ
cũ nếu cần thiết..
Maximum() Trả lại kích thước của sequence.
length() Hai phương thức được định nghĩa cho việc đặt và trả lại chiều dài
của sequence.
Operator[]() Hai toán tử chỉ mục được cung cấp cho việc truy nhập một phần tử
trong sequence. Một toán tử cho phép phần tử được thay đổi còn
một toán tử chỉ cho phép truy nhập đọc phần tử.
_release() Giải phóng sequence. Nếu cờ giải phóng của bộ tạo lập là khác 0
khi đối tượng được khởi tạo và kiểu phần tử của sequence là một
chuỗi hoặc tham chiếu đối tượng thì mỗi phần tử sẽ được giải
phóng trước khi buffer được giải phóng.
allocbuf()
freebuf()
Bạn nên dùng hai phương thức tĩnh này để cấp phát hay huỷ bất kỳ
bộ nhớ nào sử dụng bởi một sequence
Quản lý bộ nhớ về các sequence
Bạn nên cân nhắc cẩn thận các vấn đề quản lý bộ nhớ được chỉ ra dưới đây:
• Nếu cờ giải phống được đặt giá trị khác 0 khi sequence được khởi tạo,
thì sequence sẽ giả định quản lý bộ nhớ của người dùng. Khi một phần
tử được gán, bộ nhớ cũ được giải phóng trước khi quyền sở hữu của bộ
nhớ của biểu thức bên tay phải được thừa nhận.
• Nếu cờ giải phóng được đặt giá trị khác 0 khi sequence được khởi tạo
và các phần tử của sequence là các chuỗi hay các tham chiếu đối tượng,
mỗi phần tử sẽ được giải phóng trước khi buffer chứa nội dung của

sequence được giải phóng và đối tượng bị huỷ.
• Tránh việc gán một phần tử của sequence sử dụng toán tử [] trừ khi cờ
giải phóng được đặt là 1, hoặc lỗi quản lý bộ nhớ xuất hiện.
• Các sequence được khởi tạo với cờ huỷ đặt bằng 0 không nên được sử
dụng như các tham biến đầu vào/ đầu ra bởi vì các lỗi quản lý bộ nhớ
trong bộ dịch vụ đối tượng có thể đưa đến kết quả.
- 9 -
• Luôn luôn sử dụng allocbuf và freebuf để khởi tạo và giải phóng kho
lưu trữ được sử dụng với các sequence.
h> Array
Các array của IDL được ánh xạ sang các array của C++, cái mà có thể
được khởi tạo tĩnh. Nếu các phần tử của array là các chuỗi hoặc các tham
chiếu đối tượng, thì các phần tử của mảng trong C++ có kiểu _var. Ví dụ
đoạn chương trình sau chỉ ra ba mảng với các kiểu phần tử khác nhau.
// IDL
interface Intf
{
// definitions...
};
typedef long L[10];
typedef string S[10];
typedef Intf A[10]; // kiểu tham chiếu đối tượng
...
// Kết quả trong C++
typedef CORBA::Long L[10];
typedef CORBA::String_var S[10];
typedef Intf_var A[10];
Cách sử dụng kiểu được quản lý kiểu _var cho các chuỗi và các tham
chiếu đối tượng cho phép bộ nhớ được quản lý trong suốt khi các phần
tử của mảng được gán.

Các slice của mảng
Kiểu _slice của mảng được sử dụng khi truyền tham số cho các mảng nhiều
chiều. Một slice của một mảng với tất cả các chiều của mảng gốc trừ chiều
đầu tiên. Kiểu mảng _slice cung cấp một cách thuận lợi cho việc truyền và trả
lại các tham số. Một định ngh ĩa ki ểu cho m ỗi slice được phát sinh.
// IDL
typedef long L[10];
typedef string str[1][2][3];
...
// Results in the generation of these slices
typedef CORBA::Long L_slice[10];
typedef CORBA::String_var str_slice[2][3];
typedef str_slice *str_slice_ptr;
Nếu bạn chỉ có mảng một chiều, một mảng slice chỉ là một kiểu. Như bạn
thấy ở ví dụ trên, ta có mảng long L[10] thì một mảng slice sẽ trả lại kết quả
trong kiểu dữ liệu là CORBA::Long
- 10 -
Quản lý bộ nhớ cho các mảng
Trình biên dịch IDL của C++ sinh ra hai hàm phục vụ cho việc cấp phát và
giải phóng bộ nhớ kết hợp với các mảng. Các hàm này cho phép ORB quản lý
bộ nhớ mà không ghi đè các toán tử new và delete.
// IDL
typedef long L[10];
...
// Kết quả trong C++
inline L_slice *L_alloc(); // Cấp phát động một mảng. Trả lại giá
trị NULL nếu lỗi.
inline void L_free(L_slice *data); // Giải phóng bộ nhớ mảng được cấp
phát bởi L_loc.
* Quản lý các ngoại lệ (Exception)

Một exception trong Idl được ánh xạ sang một lớp của C++. Lớp này chứa
các thành phần sau:
• Các bộ tạo lập (constructor)
• Destructors
• Một hàm _narrow static để xác định kiểu của exception.

// OMG IDL
module INVENT
{
exception NonExist
{
ID BadId;
};
};
// C++
class INVENT
{
. . .
class NonExist : public CORBA::UserException
{
public:
static NonExist * _narrow(CORBA::Exception_ptr);
NonExist (ID _BadId);
NonExist ();
NonExist (const NonExist &);
~NonExist ();
- 11 -
NonExist & operator=(const NonExist &);
void _raise ();
ID BadId;

};
};
Các thuộc tính của lớp Exception là public vì vậy bạn có thể truy nhập trực
tiếp.
Ánh xạ các các bộ phận
Các bộ phận của lớp ngoại lệ được ánh xạ theo cách tương tự như các cấu
trúc. Tất cả các bộ phận của ngoại lệ là dữ liệu công cộng trong lớp của C++,
và được truy nhập trực tiếp.
Var
Một lớp _var được sinh ra cho một ngoại lệ.
Out
Một lớp Out được sinh ra cho một ngoại lệ.
Các hàm bộ phận
Với ngoại lệ của IDL là TYPE có các hàm bộ phận sau:
static TYPE * _narrow(CORBA::Exception_ptr Except);
TYPE(); Đây là constructor mặc định cho ngoại lệ
TYPE(các tham chiếu bộ phận);
TYPE (const TYPE & From);
~TYPE ();
TYPE & operator=(const TYPE & From);
void _raise ();
* Quản lý các giao diện (interface)
Một giao diện trong IDL được ánh xạ sang một lớp của C++. Lớp này
chứa các định nghĩa của các thao tác, các thuộc tính, các hằng, và các kiểu
người dùng định nghĩa (UDTs).
Với một giao diện INTF, đoạn mã giao diện được sinh ra chứa các phần
sau:
• Kiểu tham chiếu đối tượng (INTF_ptr)
• Kiểu biến tham chiếu đối tượng (INTF_var)
• Hàm bộ phận tĩnh _duplicate

• Hàm bộ phận tĩnh _narrow
• Hàm bộ phận tĩnh _nil
• UDTs
• Các hàm bộ phận về các thuộc tính và các thao tác
- 12 -
Xét ví dụ sau:
// OMG IDL
module INVENT
{
interface Order
{
void cancelOrder ();
};
};
Ánh xạ sang C++ như sau:
// C++
class INVENT
{
. . .
class Order;
typedef Order * Order_ptr;
class Order : public virtual CORBA::Object
{
. . .
static Order_ptr _duplicate(Order_ptr obj);
static Order_ptr _narrow(CORBA::Object_ptr obj);
static Order_ptr _nil();
virtual void cancelOrder () = 0;
. . .
};

};
Các kiểu tham chiếu đối tượng và các hàm bộ phận được mô tả như sau:
static INTF_ptr _duplicate (INTF_ptr Obj)
Hàm bộ phận tĩnh này sao chép một tham chiếu đối tượng INTF đang tồn tại
và trả lại một tham chiếu đối tượng INTF mới. Tham chiếu đối tượng INTF
mới phải được giải phóng bằng việc gọi hamf bộ phận CORBA::realease. Nếu
một lỗi xuất hiện thì một tham chiếu tới đối tượng INTF nil được trả lại. Đối
số Obj xác định tham chiếu đối tượng được sao chép.
static INTF_ptr _narrow (CORBA::Object_ptr Obj)
Hàm bộ phận tĩnh này trả lại một tham chiếu đối tượng INTF mới dựa vào
một tham chiếu đối tượng CORBA::Object_ptr đang tồn tại. Tham chiếu đối
tượng Obiect_ptr có thể được khởi tạo bằng việc gọi hàm bộ phận
CORBA::ORB::string_to_object hoặc có thể được trả lại như một tham chiếu
từ một thao tác.
- 13 -
Tham chiu i tng INTF_ptr phi tng ng vi mt i tng INTF
hoc tng ng vi mt i tng m k tha t i tng INTF. Tham chiu
i tng INTF mi phi c gii phúng bng vic gi hm b phn
CORBA::release. i s Obj xỏc nh tham chiu i tng thu hp ti
mt tham chiu i tng INTF. Tham bin Obj khụng b thay i bi cỏc
hm b phn ny v nờn oc gii phúng bi ngi s dng khi nú khụng
c s dng na. Nu Obj khụng c thu hp ti mt tham chiu i tng
INTF thỡ mt tham chiu i tng INTF nil c tr li.
static INTF_ptr _nil ( )
Hm b phn static ny tr li mt tham chiu i tng nil mi cho giao
din INTF. Tham chiu mi khụng phi c gii phúng bng cỏch gi hm
b phn CORBA::release.
Cỏc kiu tham chiu i tng
Mt lp giao din (INTF) l mt lp o; CORBA chun khụng cho phộp bn:
Khi to hay hold mt instance ca lp giao din.

S dng mt con tr hay mt tham chiu ti mt lp giao din.
Thay vỡ ú bn cú th s dng mt kiu tham chiu i tng: lp INTF_ptr
hay INTF_var.
Bn cú th ginh c tham chiu i tng bng vic s dng hm b phn
static _nrrow. Cỏc thao tỏc truy nhp trờn cỏc lp ny thỡ s dng toỏn t ->
Lp _var ca INTF n gin hoỏ vic qun lý b nh bng vic hu t ng
tham chiu i tng khi lp _var ca INTF nm ngoi phm vi c cp
phỏt li.
Cỏc thuc tớnh
Mt thuc tớnh ch c trong OMG IDL c ỏnh x sang mt hm C++ m
hm ú tr li giỏ tr thuc tớnh. Mt thuc tớnh c-ghi ỏnh x sang hai hm
C++ c chũng hm, mt hm tr li giỏ tr thuc tớnh v mt hm tr li tp
giỏ tr thuc tớnh. Tờn ca hm b phn c chng hm l tờn ca thuc tớnh.
Cỏc thuc tớnh c to ra theo cỏch tng t m cỏc hm c to ra.
II. ánh xạ phía server
Trong phần này chúng ta sẽ xem cách mà các giao tiếp IDL ánh xạ sang
các lớp C++ cùng với sự hỗ trợ việc tạo và gọi đối tợng CORBA ở bên phía
server và một số vấn đề liên quan khác .
1 . Mở đầu :
Trong mô hình CORBA các đối tợng server thực hiện bởi ứng dụng
server.Tại server, đối tợng CORBA đợc thực thi và thể hịên bởi các hàm ngôn
- 14 -

×