2010-03-17 12 views
10

Tôi muốn xây dựng một số mã gọi một số mã khi tải lên thư viện được chia sẻ. Tôi nghĩ tôi sẽ làm điều đó như thế này:#pragma init và #pragma fini sử dụng trình biên dịch gcc trên linux

#pragma init(my_init) 

static void my_init() { 
    //do-something 
} 

int add (int a,int b) { 
    return a+b; 
} 

Vì vậy, khi tôi xây dựng mã với

gcc -g -fPIC -c Wall tt.c

Nó trả

gcc -fPIC -g -c -Wall tt.c 
tt.c:2: warning: ignoring #pragma init 
tt.c:4: warning: ‘my_init’ defined but not used 

Vì vậy, nó bỏ qua #pragmas của tôi. Tôi đã thử điều này trong mã thực và mã của tôi bị hủy bỏ bởi vì một hàm không được gọi trong phần pragma bởi vì nó bị bỏ qua.

Làm cách nào để tôi nhận được gcc để sử dụng các câu lệnh #pragma init và fini này?

Trả lời

16

pragmas gần như là tất cả các trình biên dịch cụ thể. GCC không thực hiện init, nhưng bạn có thể có được hiệu quả tương tự bằng cách sử dụng thuộc tính constructor chức năng:

static __attribute__((constructor)) void my_init() 
{ 
    //do-something 
} 

Ngoài ra còn có một destructor thuộc tính tương ứng.

+0

chính xác những gì tôi đang tìm kiếm! – Josh

+0

Hm, đối với gcc 4.4.6 Tôi nhận được 'dự kiến', 'hoặc ‘;’ trước lỗi ‘{’ token' với ví dụ trên. Khi tôi loại bỏ các thuộc tính từ định nghĩa chức năng và đặt một khai báo hàm với thuộc tính constructor trước nó, nó hoạt động như mong đợi/[documented] (http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html). – maxschlepzig

+0

@maxschlepzig: Thuộc tính cần phải trước khai báo trong định nghĩa hàm, được cập nhật. – caf

-2

Thay vào đó, sử dụng C++:

 
// init.cpp 
namespace // an anonymous namespace 
{ 
    class autoinit 
    { 
     public: 
      ~autoinit(){ /* destruction code, if applicable */ } 
     private: 
      autoinit(){ /* content of myinit */ } 
      static autoinit _instance; 
    }; 

    autoinit 
    autoinit::_instance; // static instance forces static construction 
} 
+0

Ông có thể yêu cầu mã của mình được gọi trước khi bất kỳ nhà thầu tĩnh nào được gọi trong trường hợp này có thể không hoạt động (thứ tự khởi tạo không thể được kiểm soát và không được bảo đảm) và thực sự không thể thực hiện trong tiêu chuẩn C++. –

+0

@Grant, bạn có thể kiểm soát thứ tự tương đối của hàm được khai báo với __attribute __ ((constructor)) không? Nếu không, làm thế nào là nó khác nhau? Bên cạnh đó, phương pháp này là di động trên tất cả các triển khai C++, trong khi cú pháp __attribute __ ((constructor)) chỉ là GCC. –

+1

Tôi tin rằng cú pháp __attribute __ ((constructor)) đảm bảo rằng nó được gọi trước tất cả các mã khác. Ngoài ra, nó cho phép bạn chỉ định một ưu tiên cho hàm tạo đó vì vậy nếu nhiều được xác định nó biết thứ tự để chạy chúng. Như với tính di động, tôi đã nói rằng có mã của bạn được gọi trước bất kỳ nhà xây dựng lớp tĩnh (tức là kiểm soát khởi tạo) isn Không thể thông qua chuẩn C++, không có cách nào để thực hiện nó. Bạn chỉ đơn giản là chỉ ra những gì tôi đã nói và phương thức của bạn vẫn không cho phép mã chạy trước bất kỳ lớp tĩnh nào. –