2011-06-30 49 views
40

Tôi liên kết với hai thư viện được chia sẻ khác nhau. Cả hai thư viện đều xác định một số biểu tượng có chung tên nhưng có các cách triển khai khác nhau. Tôi không thể làm cho mỗi thư viện sử dụng việc triển khai của riêng mình qua thư viện khác.Liên kết hai thư viện được chia sẻ với một số biểu tượng giống nhau

Ví dụ: cả hai thư viện xác định hàm toàn cầu bar() mà mỗi cuộc gọi đều gọi nội bộ. Một thư viện gọi nó từ foo1() và thư viện hai gọi nó từ foo2().

Lib1.so:

T bar 
T foo1()  // calls bar() 

Lib2.so:

T bar 
T foo2()  // calls bar() 

Nếu tôi liên kết ứng dụng của tôi chống lại Lib1.so và sau đó Lib2.so việc thực hiện thanh từ Lib1.so được gọi là thậm chí khi gọi foo2(). Nếu mặt khác, tôi liên kết ứng dụng của tôi với Lib2.so và sau đó Lib1.so, sau đó thanh luôn được gọi từ Lib2.so.

Có cách nào để làm cho thư viện luôn thích việc triển khai của chính nó trên bất kỳ thư viện nào khác không?

Trả lời

40

Có một số cách để giải quyết này:

  • đèo -Bsymbolic hoặc -Bsymbolic-functions để mối liên kết. Điều này có tác dụng toàn cầu: mọi tham chiếu đến một biểu tượng toàn cầu (của kiểu hàm cho -Bsymbolic-functions) có thể được giải quyết thành một biểu tượng trong thư viện được giải quyết cho biểu tượng đó. Với điều này, bạn sẽ mất khả năng kết nối các cuộc gọi thư viện nội bộ với các ký hiệu đó bằng cách sử dụng LD_PRELOAD. Các biểu tượng vẫn được xuất, vì vậy chúng có thể được tham chiếu từ bên ngoài thư viện.

  • Sử dụng mã số phiên bản để đánh dấu biểu tượng là địa phương vào thư viện, ví dụ: sử dụng một cái gì đó như: {local: bar;}; và vượt qua --version-script=versionfile đến trình liên kết. Các biểu tượng là không xuất hiện.

  • Đánh dấu biểu tượng với một approppiate tầm nhìn (GCC info page for visibility), mà sẽ là một trong hai hidden, nội, hoặc bảo vệ.bảo vệ tầm nhìn những biểu tượng được xuất khẩu như .protected, ẩn những biểu tượng không xuất khẩunội những biểu tượng không xuất khẩu và bạn thỏa hiệp không gọi họ từ bên ngoài thư viện, thậm chí gián tiếp thông qua chức năng con trỏ.

Bạn có thể kiểm tra những biểu tượng nào được xuất với objdump -T.

+0

Xin chào, bạn có thể cho tôi biết điều này có áp dụng cho tiếng kêu không? –

3

Bạn sẽ phải tạo hai lib được chia sẻ 'wrapper', một cho mỗi libs hiện có của bạn. Mỗi cái phải được xây dựng với một danh sách --namnamic chỉ liệt kê một vài biểu tượng không xung đột xác định một API. Bạn cũng sẽ cần -Bymymbolic để tránh bất kỳ sự kết hợp toàn cầu nào.

Nó có thể ít căng thẳng hơn để truy cập libs kết quả thông qua dlopen với các tùy chọn phù hợp.

+0

Cảm ơn rất nhiều! Chỉ cần tùy chọn -Bymymbolic (được chuyển tới trình liên kết bằng tùy chọn -Wl) cho cả hai liên kết thư viện được chia sẻ đã giải quyết được vấn đề cho tôi. – drewag

0

Một cách khác để giải quyết vấn đề này là sử dụng macro để thay đổi không gian tên.

Điều kiện tiên quyết

  • Tất cả các yếu tố (các chức năng, các lớp học, các biến toàn cầu, ...) đang ở trong một không gian tên.
  • Thư viện không phụ thuộc nhiều vào các macro trong tiêu đề.

Giải pháp

  • Khi biên dịch thư viện, xác định vĩ mô với tên namespace để xác định nó một cái gì đó khác nhau. Ví dụ: nếu không gian tên là LibNS, hãy sử dụng -DLibNS=LibNSv1 cho một trường hợp và -DLibNS=LibNSv2 cho trường hợp còn lại.
  • Khi sử dụng thư viện trong mã, hãy xác định macro theo tình hình hiện tại của bạn;

    #define LibNS LibNSv1 
    #include "my_lib.h" 
    #undef LibNS 
    

Lý do tại sao sử dụng này thay vì các giải pháp khác

  • Khi thư viện có vấn đề được sử dụng (ít nhất là một phần) trong các tập tin tiêu đề (ví dụ mẫu, inlines, ...); khi bạn đưa chúng vào mã thực thi của bạn, trình giải quyết không có ý tưởng cho dù các hàm này nên được gọi từ Lib1.so hay Lib2.so. Trình biên dịch của bạn kém/không hỗ trợ cho các giải pháp khác (không nên xảy ra với CPU intel/amd 32/64 bit của chúng tôi, nhưng có vẻ như từ tìm kiếm của Google mà một số nền tảng khác có thể gặp sự cố).

cố có thể xảy

  • Nó có thể là vấn đề sử dụng cả hai phiên bản trong một tập tin cpp của thực thi của bạn; #include "my_lib.h" có thể sử dụng macro để bảo vệ chống lại việc thêm nhiều và không xác định chúng để tránh điều này có thể gây ra nhiều vấn đề khác nhau (tác giả thư viện có thể thay đổi tên macro trong tương lai, tiêu đề xác định một số macro khác, v.v.).

Ghi chú

  • này không có nghĩa là để thay thế câu trả lời chấp nhận hiện nay (từ ninjalj; cảm thấy tự do để sao chép-dán), nhưng mở rộng nó với cách tiếp cận khác.
  • Lý do chính khiến tôi đăng câu trả lời này là tôi đã gặp sự cố này ngày hôm nay, nhưng câu trả lời không giúp được gì do mã có vấn đề nằm trong tệp tiêu đề.
  • Nguồn của tôi: https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/
Các vấn đề liên quan