2012-03-30 28 views
24

Tôi bị kẹt trong một tình huống đối số truyền trong libev.Libev, Cách chuyển đối số cho các cuộc gọi lại có liên quan

Thông thường, libev nhận gói trong một chức năng như * receive_callback *, đó là OK, nhưng trong thực tế, chúng ta cần phải cử một người họ hàng * write_callback * để đối phó với công việc cụ thể theo gói nhận được. Ví dụ:

S_RECV_MSG* pstRecvMsg = (S_RECV_MSG*) recv_buff; 
switch(pstRecvMsg->wMsgType) { 
    case 1: 
     ev_io_init(w, write_callback1, w->fd, EV_WRITE); 
     break; 
    case 2: 
     ev_io_init(w, write_callback2, w->fd, EV_WRITE); 
     break; 
    case 3: 
     // ....... 
} 

Câu hỏi của tôi là, nếu write_callbackX cũng phải đọc nội dung cụ thể trong recv_buff, làm thế nào chúng ta có thể vượt qua đối số recv_buff đến callbackX? Chúng ta có phải chịu gánh nặng và sự xấu xa của các biến toàn cầu ở đây không?

+18

Đó là câu trả lời đúng, nếu bạn muốn bạn có thể viết nó như là một câu trả lời thực sự và chấp nhận nó, giúp người khác dễ dàng tìm thấy thông tin hơn. – dnaq

+3

Ít nhất bạn quay trở lại và tiếp tục nghiên cứu thay vì chờ đợi một câu trả lời :) Vui vì bạn đã giải quyết nó. –

+15

Tôi đề nghị viết giải pháp của bạn như là một câu trả lời (và sau đó chấp nhận nó) thay vì chỉnh sửa nó trong câu hỏi – Shahbaz

Trả lời

5

Tác giả đã tự trả lời, nhưng trong nhận xét. Vì điều này hiển thị là chưa được trả lời, tôi đang đăng câu trả lời của mình trong phần "câu trả lời" và đóng vòng lặp. Không chắc chắn nếu có một cách tốt hơn ... cảm thấy tự do để sửa lỗi này.

Câu hỏi tác giả nói:

Xin lỗi, tôi nghĩ rằng tôi có câu trả lời bây giờ, và cảm thấy xấu hổ sâu sắc tại bất cẩn của tôi về tài liệu hướng dẫn đọc:

struct my_io{ 
    ev_io io; 
    int otherfd; 
    void *somedata; 
    struct whatever *mostinteresting; 
}; 
// ... 
struct my_io w; 
ev_io_init (&w.io, my_cb, fd, EV_READ); 

Và sau đó chúng tôi sử dụng my_io như này:

static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) 
{ 
    struct my_io *w = (struct my_io *)w_; 
    //... 
} 
+0

nếu tôi đang sử dụng bộ nhớ heap trong somedata, cách tiếp cận chính xác để giải phóng nó là gì? –

+0

Tôi không hiểu. Làm thế nào có thể ev_io * w_ được đúc thành (struct my_io *) trong gọi lại my_cb? – lppier

+0

@lppier 'ev_io' là thành viên đầu tiên trong' my_io' do đó địa chỉ của nó có thể được lấy bởi dàn diễn viên đó. –

1

Có nó giải thích trong tài liệu libev, và có một cách khác. Mỗi watcher có thành viên dữ liệu void * mà bạn có thể đọc hoặc sửa đổi, và hoàn toàn libev sẽ bỏ qua nó, vì vậy bạn có thể vượt qua đối số như thế này:

w->data = (void *)recv_buff; 
... 
static void my_cb (struct ev_loop *loop, ev_io *w_, int revents) 
{ 
    S_RECV_MSG *recv_buff = (S_RECV_MSG*)w_->data; 
    ... 
} 

thấy libev document.

+0

sử dụng -> dữ liệu là cách tốt hơn để làm điều đó hơn là kỹ thuật 'phân lớp' – matiu

Các vấn đề liên quan