2011-01-30 8 views
5

Tôi hiện đang sử dụng chức năng popen trong mã được biên dịch bởi hai trình biên dịch: MS Visual Studio và gcc (trên Linux). Tôi có thể muốn thêm gcc (trên MinGW) sau.Cách tiêu chuẩn nhất để chọn tên hàm tùy thuộc vào nền tảng?

Các hàm được gọi popen cho gcc, nhưng _popen cho MSVS, vì vậy tôi thêm vào sau vào mã nguồn của tôi:

#ifdef _MSC_VER 
#define popen _popen 
#define pclose _pclose 
#endif 

này hoạt động, nhưng tôi muốn tìm hiểu xem liệu có tồn tại một giải pháp tiêu chuẩn cho những vấn đề như vậy (tôi nhớ lại một trường hợp tương tự với stricmp/strcasecmp). Cụ thể, tôi muốn hiểu những điều sau:

  1. Có phải là _MSC_VER cờ phải phụ thuộc vào không? Tôi đã chọn nó bởi vì tôi có ấn tượng rằng môi trường Linux là "tiêu chuẩn hơn".
  2. Nếu tôi đặt các số #define này vào một số tệp tiêu đề, điều quan trọng là tôi có #include trước hoặc sau stdio.h (đối với trường hợp popen)?
  3. Nếu _popen được định nghĩa là macro, có khả năng số #define của tôi sẽ không thành công? Tôi có nên sử dụng mã thông báo "mới" như my_popen thay vì, vì lý do đó hay cách khác không?
  4. Có ai đó đã làm công việc này cho tôi và tạo một tệp "tiêu đề khả năng di động" tốt mà tôi có thể sử dụng không?
  5. Bất kỳ điều gì khác mà tôi cần phải biết?

Trả lời

1

Cách bạn đang làm việc đó là tốt (với số #ifdef v.v.) nhưng macro bạn thử nghiệm không phải là. popen là cái gì đó phụ thuộc vào hệ điều hành của bạn chứ không phải trình biên dịch của bạn.

tôi muốn đi cho một cái gì đó giống như

#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 2) 
/* system has popen as expected */ 
#elif defined(YOUR_MACRO_TO DETECT_YOUR_OS) 
# define popen _popen 
# define pclose _pclose 
#elif defined(YOUR_MACRO_TO DETECT_ANOTHER_ONE) 
# define popen _pOpenOrSo 
# define pclose _pclos 
#else 
# error "no popen, we don't know what to do" 
#endif 
1
  1. _MSC_VER là macro chính xác cho việc phát hiện các trình biên dịch MSVC. Bạn có thể sử dụng __GNUC__ cho GCC.

  2. Nếu bạn đang sử dụng popen như ID macro của bạn, tôi khuyên bạn nên #include nó sau đó, vì 3.

  3. Nếu bạn #include nó sau khi stdio.h, cần làm việc AFAIK, nhưng tốt hơn an toàn hơn xin lỗi , không? Gọi nó là portable_popen hoặc gì đó.

  4. Nhiều dự án (kể cả một số dự án của tôi) có tiêu đề có thể di chuyển, nhưng tốt hơn là nên tự cuộn. Tôi là một fan hâm mộ tự làm những việc nếu bạn có thời gian. Vì vậy, bạn biết các chi tiết của mã của bạn (dễ dàng hơn để gỡ lỗi nếu mọi thứ đi sai), và bạn nhận được mã đó là phù hợp với nhu cầu của bạn.

  5. Không phải là tôi biết. Tôi làm mọi thứ như thế này mọi lúc, không có vấn đề gì.

3
  1. Tốt hơn để kiểm tra một cửa sổ cụ thể xác định (_WIN32 lẽ) vì mingw sẽ không có điều đó. popen() được chuẩn hóa (đó là số part of the Single UNIX® Specification v2)
  2. Không; miễn là macro được xác định trước lần sử dụng đầu tiên, không quan trọng nếu _popen() không được xác định cho đến sau này.
  3. Không; những gì bạn có là tốt ngay cả khi _popen là một macro.
  4. Nó được thực hiện nhiều lần nhưng tôi không biết về một phiên bản được cấp phép tự do mà bạn có thể sử dụng.
0

Thay vì kết thúc với các tập tin lộn xộn chứa #ifdef .. #else .. #endif khối, tôi muốn một phiên bản sử dụng các file khác nhau cho các nền tảng khác nhau:

  • đặt các định nghĩa phụ thuộc hệ điều hành trong một tập tin cho mỗi nền tảng và #define macro my_popen
  • #include tệp này trong mã nền tảng bất khả tri của bạn
  • không bao giờ gọi trực tiếp các chức năng của hệ điều hành, nhưng là #define mà bạn đã tạo (tức là my_popen)
  • tùy thuộc vào hệ điều hành của bạn, sử dụng tiêu đề khác nhau cho biên soạn (ví dụ config/windows/mydefines.h trên cửa sổ và config/linux/mydefines.h trên Linux, vì vậy thiết lập bao gồm đường dẫn thích hợp và luôn #include "mydefines.h")

Đó là một cách tiếp cận sạch hơn nhiều so với việc hệ điều hành quyết định trong chính nguồn.

Nếu các phương pháp bạn đang gọi cư xử khác nhau giữa các cửa sổ và Linux, quyết định cái nào sẽ là hành vi mà bạn đang sử dụng (ví dụ một trong hai luôn cửa sổ hành vi hoặc luôn hành vi linux) và sau đó tạo ra các phương pháp wrapper để đạt được điều này. Đối với điều đó, bạn cũng sẽ cần không chỉ hai tệp mydefines.h mà còn cho các tệp myfunctions.c nằm trong các thư mục config/OSTYPE.

Làm như vậy, bạn cũng có được lợi thế khi nói đến khác biệt giữa phiên bản linux và cửa sổ: bạn có thể chỉ cần tìm hai tệp trong khi thực hiện khác biệt trên khối linux và cửa sổ của cùng một tệp. .