Tôi có một chút "hàng hóa bị hỏng" khi nói đến chủ đề này. Tôi đã từng thiết kế và duy trì các API khá lớn cho viễn thông được nhúng. Một bối cảnh mà bạn không thể lấy bất cứ điều gì để được cấp. Không, ngay cả những thứ như biến toàn cục hay TLS. Đôi khi ngay cả bộ đệm heap hiện lên mà thực sự được giải quyết bộ nhớ ROM. Do đó, nếu bạn đang tìm "mẫu số chung thấp nhất", bạn cũng có thể muốn nghĩ về cấu trúc ngôn ngữ nào có sẵn trong môi trường đích của bạn (trình biên dịch có khả năng chấp nhận bất cứ điều gì trong tiêu chuẩn C, nhưng nếu có điều gì đó không được hỗ trợ, trình liên kết sẽ nói không).
Có nói rằng, Tôi sẽ luôn thay thế 1. Một phần vì (như những người khác đã chỉ ra), bạn không bao giờ nên cấp phát bộ nhớ cho người dùng một cách trực tiếp (một cách tiếp cận gián tiếp được giải thích sâu hơn). Ngay cả khi người dùng được đảm bảo làm việc với C thuần túy và thuần túy, họ vẫn có thể sử dụng API quản lý bộ nhớ tùy chỉnh của riêng họ để theo dõi rò rỉ, ghi nhật ký chẩn đoán, vv.
Thông báo lỗi là một trong những điều quan trọng nhất khi giao dịch với API. Vì người dùng có thể có các cách khác nhau để xử lý các lỗi trong mã của mình, bạn nên nhất quán nhất có thể về giao tiếp này trong suốt API. Người dùng có thể xử lý lỗi theo hướng API của bạn theo cách nhất quán và với mã tối thiểu. Tôi thường sẽ luôn khuyên bạn nên sử dụng mã enum rõ ràng hoặc định nghĩa/typedefs. Cá nhân tôi thích typedef: ed enums:
typedef enum {
RESULT_ONE,
RESULT_TWO
} RESULT;
..bởi vì nó cung cấp an toàn kiểu/bài tập.
Có chức năng get-last-error cũng tốt (yêu cầu lưu trữ trung tâm), cá nhân tôi chỉ sử dụng nó để cung cấp thêm thông tin về lỗi đã được nhận dạng.
Các verbosity của phương án 1 có thể được hạn chế bằng cách làm cho các hợp chất đơn giản như thế này:
struct Buffer
{
unsigned long size;
char* data;
};
Sau đó api của bạn có thể trông đẹp hơn:
ERROR_CODE func(params... , Buffer* outBuffer);
Chiến lược này cũng mở ra cho phức tạp hơn cơ chế. Nói ví dụ bạn PHẢI có thể phân bổ bộ nhớ cho người sử dụng (ví dụ như nếu bạn cần phải thay đổi kích thước bộ đệm), sau đó bạn có thể cung cấp một cách tiếp cận gián tiếp như sau:
struct Buffer
{
unsigned long size;
char* data;
void* (*allocator_callback)(unsigned long size);
void (*free_callback)(void* p);
};
Ofcourse, phong cách của các cấu trúc như vậy luôn luôn là mở cho cuộc tranh luận nghiêm túc.
Chúc may mắn!
Không phải loại đệm là char **? Ngoài ra, tại sao bạn cần một buffer_size trong tùy chọn một và không phải trong tùy chọn hai? – mweerden
Ông vượt qua một bộ đệm preallocated như tham số trong và hy vọng các chức năng được gọi là để điền vào nó với văn bản lỗi. – sharptooth
Ok, nhưng sau đó buffer_size không cần phải là một con trỏ, phải không? – mweerden