2012-07-30 25 views
6

Tôi đang cố gắng xây dựng thư viện được chia sẻ bằng cách sử dụng gcc 4.6 trên Linux, được tải động. Như được mô tả trong nhiều bài viết trên web cũng như trong các câu hỏi trước, tôi cung cấp các phương thức nhà máy kiểu c trong thư viện để tạo và phá hủy các đối tượng. Mã này - ở dạng tối thiểu - trông như thế này:Biểu tượng không xác định "typeinfo" với thư viện được tải động

base.h:

class base { 
public: 
    base(); 
    virtual ~base(); 
    virtual int value() = 0; 
}; 

base.cpp:

#include "base.h" 
base::base() {} 
base::~base() {} 

main.cpp:

#include "base.h" 
#include <dlfcn.h> 
#include <iostream> 

int main() { 
    void* handle = dlopen("liblib.so", RTLD_NOW); 
    if(handle == NULL) std::cout << dlerror() << std::endl; 

    // dlsym, ... 
} 

lib. cpp:

class derived : public base { 
public: 
    derived() {} 
    virtual ~derived() {} 
    virtual int value() { return 42; } 
}; 

extern "C" derived* create_object() { 
    return new derived(); 
} 

Nó biên dịch tốt với:

g++ -shared -fPIC lib.cpp -o liblib.so 
g++ base.cpp main.cpp -ldl -o app 

Khi chạy tuy nhiên nó bị treo vì một thiếu typeinfo biểu tượng

liblib.so: undefined symbol: _ZTI4base 

Trong câu hỏi trước đó tôi tìm thấy ở đây, lỗi này là thường là do một trong hai số mất tích "= 0;" hoặc thiếu định nghĩa của một hàm ảo. Trong ví dụ trên, base :: value là pure virtual và destructor có định nghĩa. Kỳ lạ đủ các báo cáo nm _ZTI4base như được xác định trong ứng dụng:

$ nm app | grep _ZTI4base 
0000000000601050 V _ZTI4base 

Vậy tại sao người liên kết không sử dụng định nghĩa này?

Cách duy nhất tôi tìm thấy cho đến nay để làm cho mã hoạt động là triển khai thực thi và destructor trong tệp tiêu đề. Tuy nhiên, sau khi thực hiện điều này, các ký hiệu tương ứng cho base được báo cáo trong liblib.so bởi nm và hoàn toàn biến mất khỏi ứng dụng, điều này có nghĩa là định nghĩa của chúng được biên dịch vào thư viện chứ không phải vào ứng dụng, không phải là thứ tôi muốn đạt được. Có ai một ý tưởng làm thế nào để có được ở trên làm việc mà không làm điều này?

+1

Đặt '--demangle' thành' nm' để xem tên bị hỏng của hàm. – Shahbaz

Trả lời

2

Bạn cần tùy chọn -rdynamic khi liên kết chương trình, để xuất ký hiệu của chương trình và cung cấp chúng cho các thư viện được tải bằng dlopen().

Các vấn đề liên quan