2011-11-10 41 views
5

Tôi muốn sử dụng cùng một phương pháp #ifdef được sử dụng bởi WxWidgets, SDL vv. Vấn đề duy nhất là tôi không biết cách sử dụng nó.Làm thế nào để bạn sử dụng bộ tiền xử lý để tạo một thư viện đa nền tảng?

Giả sử tôi muốn tạo lớp học vẽ hình chữ nhật. Tôi muốn nó sử dụng cairo khi trên nền tảng X11 (nghĩa là linux) và GDI trên nền tảng win32:

class graphics 
{ 
void drawRect(int x, int y, int w, int h) 
{ 
/*if on win32*/ 
HDC myHdc = ::BeginPaint(myHwnd,&mypstr); 
::Rectangle(myHdc,x,y,w,h); 
::EndPaint(myHwnd,&mypstr); 

/*if on x11*/ 
cairo_surface_t* s = cairo_xlib_surface_create(/* args */); 
cairo_t* c = cairo_create(s); 
cairo_rectangle(c,x,y,w,h); 
// etc. etc. 
} 
}; 

Làm thế nào tôi sẽ sử dụng #ifdef hay cái gì khác để làm điều này?

+0

Không WxWidgets và SDL cung cấp các ví dụ tiền xử lý bạn đang tìm kiếm? –

+1

(+1) Khái niệm được thể hiện bằng tiêu đề câu hỏi, đáng giá. Không có câu trả lời, đọc những người phát triển khác trả lời ... – umlcat

Trả lời

3

Nếu bạn có thể, thích đưa các phương pháp cụ thể nền tảng thành đơn vị dịch riêng biệt. Điều này sẽ cho phép mã hơn & dễ đọc hơn và dễ dàng hơn để phát triển và duy trì. IMHO, quá trình xây dựng nên xác định mô-đun cụ thể nền tảng nào để kết hợp.

Ví dụ:
rectangle.hpp:

struct Rectangle 
{ 
    void draw(int upper_left_corner_x, int upper_left_corner_y, 
      unsigned int length, unsigned int width); 
} 

Bây giờ nền tảng file cụ thể:
rectangle_wx_widgets.cpp:

#include "rectangle.hpp" 
void 
Rectangle :: 
draw(int upper_left_corner_x, int upper_left_corner_y, 
      unsigned int length, unsigned int width) 
{ 
// wxWidgets specific code here. 
} 

rectangle_qt.cpp:

#include "rectangle.hpp" 
void 
Rectangle :: 
draw(int upper_left_corner_x, int upper_left_corner_y, 
      unsigned int length, unsigned int width) 
{ 
// QT specific code here. 
} 

main.cpp:

#include "rectangl.hpp" 
int main(void) 
{ 
    Rectangle r; 
    r.draw(50, 50, 10, 5); 
    return 0; 
} 

Đoạn mã trên không có chỉ thị tiền xử lý có điều kiện. Hàm main vẽ hình chữ nhật bất kể nền tảng. Các chi tiết cụ thể của nền tảng đã bị xóa khỏi main vì chúng không quan trọng. Vì vậy, mà không thay đổi bất kỳ công tắc trình biên dịch hoặc đáng lo ngại về định danh tiền xử lý nào được xác định, người ta có thể thấy rằng main vô điều kiện vẽ một hình chữ nhật.

Để vẽ bằng nền tảng wxWidgets, quá trình xây dựng sẽ sử dụng rectangle_wx_widgets.cpp. Để vẽ bằng QT, tệp rectangle_qt.cpp sẽ được sử dụng, nhưng không được sử dụng cả hai. Như minh họa này cho thấy, không có mã nào được thay đổi để tạo mã cho cả hai nền tảng.Người ta có thể điều chỉnh quá trình xây dựng để lệnh build wxWidgets sẽ bao gồm các đơn vị dịch phù hợp. Vì vậy, việc truyền tham số cho quá trình xây dựng sẽ tạo ra nền tảng thực thi cụ thể.

+0

Tôi đồng ý rằng giải pháp của bạn có vẻ sạch hơn. (+1), nhưng tôi cảm thấy một hoặc hai vấn đề, nếu tôi muốn thay đổi một cái gì đó trong tiêu đề? ví dụ: nếu cửa sổ 'typedef HDC painter' else 'typedef cairo_t painter' – ApprenticeHacker

+0

@IntermediateHacker: Các tệp nền tảng cụ thể có thể bao gồm các tiêu đề nền tảng cụ thể. Trong ví dụ trả lời của bạn, bạn sẽ tạo một phương thức 'paint' chung là khung công cụ cụ thể. Sẽ có một 'paint' cho Windows API và một' paint' cho Cairo. Và tuyên truyền điều này càng xa càng tốt. Mục tiêu là giảm số lượng các chỉ thị tiền xử lý có điều kiện. –

+0

Cảm ơn. Giải pháp của bạn hoạt động hoàn hảo. – ApprenticeHacker

0

Chúng khá trực tiếp.

Bạn muốn một cái gì đó như thế này:

#ifndef WIN32 
// something for X11 
#else 
// something for Windows 
#endif 

Nó chỉ là một vấn đề của biết các điều kiện mặc định (như Win32 trong trường hợp này). Có điều kiện cho hệ điều hành, trình biên dịch và rất nhiều thứ di động.

Đối với trường hợp này, hãy xem tệp tiêu đề windows.h. Nó có thể chứa thêm thông tin cho bạn.

+0

bạn có thể muốn 'ifdef' để bạn có thể hỗ trợ nhiều hơn hai. –

0

Có biến nền tảng được xác định trước như Win32 mà bạn có thể sử dụng:

#ifdef WIN32 
.... 
#else 
.... 
#endif 
2

nền tảng chéo không có nghĩa là chỉ có Unix và cửa sổ. Ngoài ra, các chỉ thị cpp được xác định trước có thể phụ thuộc vào trình biên dịch. mã nguồn tăng cường lựa chọn nền tảng là một khởi đầu tốt để xem làm thế nào điều này có thể được thực hiện đúng cách. thấy config/select_platform_config.hpp bạn cũng có thể muốn có một cái nhìn tại cmake mà đặt ra một số platform dependent defines

+0

xin lỗi vì hàm ý "Unix vs Windows", nó không được dự định. Tôi chỉ muốn giải thích vấn đề. – ApprenticeHacker

+1

không có ý định chơi chữ, tôi đã chỉ làm cho quan điểm của tôi – user237419

+0

không có vấn đề gì sau đó. (+1) :) – ApprenticeHacker

0

Có một mẹo để thực hiện mà tôi không nhìn thấy những người khác nhắc đến (chỉnh sửa: sysfault đề cập đến nó). Có hai khái niệm khác nhau tại nơi làm việc ở đây. Các lệnh tiền xử lý sẽ khác nhau tùy thuộc vào cả mục tiêu của bạn và trình biên dịch của bạn. Cụ thể, để cho các trình biên dịch bạn đang sử dụng (GCC vs MSVC)

#ifdef _MSC_VER 
    /*MSVC*/ 
#endif 
#ifdef __GNUC__ 
    /*GCC*/ 
#endif 

MSVC sẽ chỉ biên dịch cho các mục tiêu Windows (như xa như chúng tôi đang quan tâm hiện nay), và GCC mục tiêu tất cả mọi thứ. Đối với GCC, để nói OS đang nhắm mục tiêu:

#ifdef __MINGW32__ 
    /* Windows */ 
#endif 
#ifdef BSD 
    /* BSD */ 
#endif 
#ifdef __linux__ 
    /* linux */ 
#endif 
#ifdef __APPLE__ 
    /* OSX */ 
#endif 

Ngoài ra, đôi khi bạn cần phải biết một cái gì đó cụ thể cho các bộ xử lý, nhưng không phải là hệ điều hành:

__CHAR_UNSIGNED__ 
    GCC defines this macro if and only if the data type char is unsigned on the target machine. 
__BYTE_ORDER__ 
__ORDER_LITTLE_ENDIAN__ 
__ORDER_BIG_ENDIAN__ 
__ORDER_PDP_ENDIAN__ 
    __BYTE_ORDER__ is defined to one of the values __ORDER_LITTLE_ENDIAN__, __ORDER_BIG_ENDIAN__, or __ORDER_PDP_ENDIAN__ to reflect the layout of multi-byte and multi-word quantities in memory. 
__LP64__ 
_LP64 
    These macros are defined, with value 1, if (and only if) the compilation is for a target where long int and pointer both use 64-bits and int uses 32-bit. 

Và nhiều nhiều người khác