2009-05-08 27 views
13

Tôi đang tạo api C mà giấu đi một số chức năng trong một tập tin DLL.Các loại phù hợp với tay cầm ở giao diện C

Kể từ khi tất cả mọi thứ là C++ ở bên trong hầu hết các chức năng làm việc chống lại xử lý mà bản đồ trực tiếp đến con trỏ này vào bên trong API.

Để có được một mức độ nào đó của loại an toàn cho những tay nắm tôi định nghĩa chúng như thế này:

typedef struct MyType1* MyType1Handle; 
typedef struct MyType2* MyType2Handle; 

Tôi không thực sự xác định MyType1 hoặc MyType2 ở bất cứ nơi nào kể từ khi tôi chỉ sử dụng chúng như con trỏ và làm một gõ vào bên trong của api để loại con trỏ thực tế.

Vấn đề của tôi là khi sử dụng thư viện của tôi trong một dự án clr trong visual studio tôi có được điều này warning: unresolved typeref token (token) for 'type'; image may not run.

http://msdn.microsoft.com/en-us/library/h8027ys9(VS.80).aspx

Đó là không có vấn đề lớn vì nó hoạt động, nhưng có vẻ không chuyên nghiệp.

tôi không thích sử dụng void *:

typedef void* MyType1Handle; 
typedef void* MyType2Handle; 

Điều này làm cho nó có thể để gọi một chức năng muốn một MyType1Handle với một MyType2Handle kể từ khi họ thực sự là cùng loại.

Một cách tiếp cận tôi không muốn sử dụng là một cái gì đó như thế này

typedef int MyType1Handle; 
typedef int MyType2Handle; 

này sẽ làm việc tốt miễn là int và con trỏ có cùng kích thước, nhưng đó không phải luôn luôn như vậy và nó có vẻ như có là không có cách nào dễ dàng để có được một con số cụ thể có kích thước nền tảng con trỏ. Nó cũng có cùng các vấn đề an toàn như void *.

Một cách tiếp cận tôi đã cố gắng là để làm điều đó như thế này:

struct MyType1{}; 
typedef struct MyType1* MyType1Handle; 

này đã không làm việc trong C kể từ khi cấu trúc rỗng là mã C không hợp lệ. Tôi tất nhiên có thể mở rộng cấu trúc của tôi với một thành viên giả, nhưng nó có vẻ như cần phải có một cách tốt hơn để làm điều này.

Vì vậy, câu hỏi của tôi tóm tắt:

Bạn thường chỉ định loại kiểu này theo cách tương thích nhất?

Trả lời

12

Nếu bạn nhìn vào cách Microsoft định nghĩa nó là xử lý WINAPI (winnt.h) nó thực sự trông như thế này:

struct HWND__ { int unused; }; typedef struct HWND__ *HWND 

trong thực tế, họ có một vĩ mô cho việc này:

#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name 

như vậy. điều này có vẻ là một thực tế phổ biến để làm như vậy. Đáng tiếc là tôi không thể thực hiện một đề nghị trừ thế này, mà bạn đã đề cập, nhưng tôi hy vọng nó sẽ giúp bạn anyway.

+0

Cảm ơn câu trả lời. Có vẻ như tôi không phải là người đầu tiên gặp vấn đề này ít nhất :) – Laserallan

+0

Một điểm khác biệt ở đây là trong các tiêu đề công khai, loại HANDLE tham chiếu đến một loại cụ thể. Cấu trúc giả được định nghĩa hoàn toàn. Tất nhiên, chúng xác định DECLARE_HANDLE khác nhau khi bao gồm các tệp đó trong quá trình triển khai. – RBerteig

3

Tôi nghĩ rằng bạn chỉ có thể tuyên bố, nhưng không xác định, cơ cấu nguồn:

struct MyType1;

typedef struct MyType1 * MyType1Handle;

8

Sử dụng cấu trúc mờ đục. Đây là một ý tưởng hay trong nhiều trường hợp khi xác định giao diện cho một thư viện trong C: nó cải thiện mô đun, ẩn các chi tiết không cần thiết

Như JamieH đã nói, bạn nhận được một cấu trúc mờ đục - không xác định - cấu trúc. Nó hoàn toàn hợp lệ để có, và vượt qua, trỏ tới cấu trúc mờ đục trong các hàm thư viện làm đối số và trả về chúng dưới dạng giá trị. Tuy nhiên, người dùng thư viện không thể tạo hoặc sửa đổi các đối tượng của cấu trúc mờ vì kích thước và nội dung của nó không xác định.

Thư viện chuẩn C và nhiều thư viện khác, đã sử dụng cách tiếp cận này vì vậy nó nên quen thuộc. Ví dụ về pháo là việc sử dụng FILE *: fopen() tạo và khởi tạo cấu trúc và trả về một con trỏ tới nó, fclose() dọn dẹp và giải phóng nó và tất cả các chức năng khác của i/o lấy bối cảnh của chúng từ thông số FILE *.

+0

Ẩn con trỏ trong typedefs thường gọi cho sự cố (nói về thông báo lỗi mà babble somethingn về con trỏ ngay cả khi chương trình của bạn dường như không sử dụng chúng hoặc ngược lại); vì vậy cách tiếp cận HWND ở trên tôi không thể khuyên bạn nên thực sự; các cấu trúc-định nghĩa-không tiếp xúc hoạt động tốt hơn. Đối với C++, vì định nghĩa lớp cần được cung cấp cho mọi thứ để làm việc, cách tiếp cận "d-con trỏ" sẽ hoạt động tốt nhất ở đây. – user502515

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