2012-01-25 41 views
6

Đây là phiên bản được viết lại hoàn toàn của an earlier question; Tôi nghĩ rằng phiên bản đầu tiên bỏ qua các chi tiết quan trọng; cái này cung cấp tất cả ngữ cảnh.Câu đố API C/C++

Tôi có tiêu đề của một số API C++. API tuyên bố một số lớp như sau:

class Foo 
{ 
public: 
    inline void Bar(void); 
    /* more inlines */ 
private: 
    inline Foo(); 
    /* maybe more inline constructors */ 
} 

I.e. không có thành viên, tất cả các hàm đều là nội dòng và công khai, ngoại trừ các hàm tạo. Các nhà xây dựng là riêng tư, vì vậy, theo như tôi hiểu C++, tôi không thể thực sự gọi chúng. Để tạo các đối tượng này tôi dự định sử dụng auto_ptr s đối với họ:

class FooAutoPtr : public std::auto_ptr<Foo> 
{ 
public: 
    inline FooAutoPtr(); 
    /* one for each Foo constructors */ 
} 

API cũng có một bộ thứ hai của các chức năng như thế này:

void Foo_Bar(void *self); 
Foo* Foo_Constructor(); 

Hãy gọi cho họ chức năng cốt lõi, bởi vì đây là những biểu tượng thực sự được xuất từ ​​ứng dụng máy chủ. Không phải các lớp C++.

Chức năng chính có liên kết C (nghĩa là chúng được khai báo là extern "C"), nhưng chúng được khai báo là lấy và trả về loại C++ (ví dụ: chúng có thể tham chiếu: Foo &foo). Cuối cùng tiêu đề chứa việc thực hiện các hàm nội tuyến của các lớp C++. Tất cả các chức năng này đều giống nhau: chúng gọi các hàm lõi. Ví dụ, các nhà xây dựng FooAutoPtr là như thế này:

inline FooAutoPtr::FooAutoPtr() 
{ 
    reset(Foo_Constructor()); 
} 

Từ những gì tôi hiểu, mã nhận được một số đối tượng được coi là một con trỏ đến Foo từ các ứng dụng máy chủ và thay đổi auto_ptr Gizmo để trỏ đến đối tượng này . Nhưng đối với nhà phát triển, có vẻ như đó là con trỏ thực sự đến Foo. Và gọi số Foo::Bar() sẽ diễn ra như sau:

inline Foo::Bar() 
{ 
    Foo_Bar(this); 
} 

Điều này áp dụng cho tất cả các lớp và phương pháp C++. Clever, huh?

Bây giờ, ai đó có thể giải thích điều này có nghĩa là gì? :) Nó không phải là một C++ API thực sự, phải không? Đối với tôi, nó trông giống như một wrapper C++ mỏng trên đầu trang của một API C. Nếu vậy, tôi có thể redeclare các chức năng cốt lõi để mất các bit C++? Tôi hiểu làm thế nào để viết một wrapper C xung quanh C + + (thực sự, tôi đã viết nó), nhưng, nếu có thể, tôi muốn mất wrapper và sử dụng các chức năng trực tiếp. Nhưng làm thế nào để mất các công cụ C++?

Ví dụ, có thể có một chức năng với sự tham khảo:

Bar& Foo_GetBar(void* self, const Baz& baz, int& i); 

Ngay bây giờ tôi gọi nó từ C của tôi ++ wrapper như thế này:

typedef struct bar bar_t; /* and others */ 
/*...*/ 
bar_t* 
foo_get_bar(foo_t* foo, baz_t* baz, int* i) 
{ 
    return (bar_t*) &Foo_GetBar(foo, *(Baz*)baz, *i); 
} 

và nó hoạt động (tôi không có ý tưởng, làm sao). Nhưng tôi thà có nó redeclared như thế này:

/* type? */ Foo_GetBar(foo_t*, /* type? /*, /* type? */); 

CẬP NHẬT: Tôi tìm thấy một điều thú vị mà khẳng định Neil's answer. Đó là mã trong Common Lisp sử dụng cùng một API. (Đương nhiên, nó phải sử dụng phần C.) Và, từ những gì tôi có thể (hầu như) đọc trong nguồn, tác giả chỉ đơn giản là sử dụng con trỏ thay cho tham chiếu.Dưới đây là một đoạn trích từ mã chuyển đổi khai báo C++ thành Lisp:

;; use * instead of & - we're not interested in C++ details 
line (regex-replace-all "&" line "*") 

Vì vậy, đó là nó :) Cảm ơn mọi người!

+8

Wow, một câu hỏi được đặt là _legitimately_ được gắn thẻ cả 'c' và' C++'. Một sự xuất hiện hiếm hoi ... – ildjarn

+2

Nếu các hàm lõi trả về các kiểu C++ (tham chiếu) thì nó _is_ một API C++ sống thực (_not_ a API C), nhưng nó không phải là một đối tượng hướng đối tượng. –

+0

@ SethCarnegie Vì vậy, đó là nó :) Bạn thấy, tiêu đề thậm chí có một bình luận gần các chức năng cốt lõi nói rằng đây là "cho môi trường C-chỉ". Vâng, một bình luận lỗi thời :) –

Trả lời

4

Về lý thuyết, chi tiết về cách trình biên dịch xử lý tham chiếu trong khai báo liên kết C là chi tiết triển khai không xác định. Tuy nhiên nhiều trình biên dịch xử lý nó như thể nó là một con trỏ. Vì vậy, nếu tiêu đề thư viện C++ nhập Bar& Foo_GetBar(void* self, const Baz& baz, int& i); thì bạn có thể thử nhập nó vào tiêu đề C của bạn dưới dạng bar_t* Foo_GetBar(foo_t* self, const baz_t* baz, int* i); và nó có thể hoạt động.

+0

Tôi sẽ cung cấp cho nó một thử. Tôi nghi ngờ một cái gì đó như thế, nhưng không quá dũng cảm để bắt đầu mà không có một xác nhận :) Cảm ơn! –

+0

BTW, tôi cập nhật các bài về mã Lisp tôi chỉ thấy rằng sử dụng cùng một API và có, nó chỉ đơn giản là sử dụng con trỏ :) Vì vậy, bạn phải. –

1
#define & * // convert references into pointers. 

Dừng. Đúng. Ở đó. Đó là một trò đùa, chứ không phải là một nỗ lực để xem có bao nhiêu downvotes có thể được tích lũy trên một câu trả lời duy nhất.

Nhưng cách tiếp cận viết lại tệp tiêu đề để thay thế tham chiếu bằng con trỏ chắc chắn sẽ hoạt động. Bởi vì đây là các hàm C, nên không có tên mangling để lo lắng, và tôi chưa thấy trình biên dịch không thực hiện các tham chiếu như con trỏ. (Có cách nào khác có thể không?)

+0

'# define' chỉ hoạt động đối với số nhận dạng, vì vậy bạn không thể thực hiện thủ thuật đó :) –

+0

@Seth: Thật vậy. Đó là chỉ là tốt, thực sự. – Roddy

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