2012-02-15 28 views
6

Tôi đang cố gắng sao chép công việc của Flavian Coelho, linked here. Ông đã sử dụng Cython và Thư viện khoa học Gnu (GSL) để có được tốc độ lớn hơn so với Python trong việc tạo ra các số ngẫu nhiên. Khi tôi nhập mã Cython biên soạn của tôi trong Python (với lệnh import cgibbs), tôi nhận được lỗi sau:NhậpError từ Cython khi liên kết thư viện C bên ngoài

ImportError: dlopen(./cgibbs.so, 2): Symbol not found: _gsl_rng_mt19937 
    Referenced from: /Users/wesley/scratch/cython/cgibbs.so 
    Expected in: dynamic lookup 

Bạn sẽ nhận thấy rằng đơn khiếu nại là biểu tượng _gsl_rng_mt19937 không thể được tìm thấy. Hàm tôi đang cố gắng liên kết đến được gọi là gsl_rng_mt19937 (không có dấu gạch dưới hàng đầu) và đó là cách nó xuất hiện trong tệp .pyx của tôi. Tôi nghĩ Cython là bằng cách nào đó gây ra vấn đề bằng cách thêm dấu gạch dưới hàng đầu đó.

Để khắc phục sự cố dễ dàng hơn, tôi đã xóa mã và đăng mã bên dưới. Hệ thống của tôi là: Mac OSX 10.7 (Sư tử) chạy Python 2.7.2 (32 bit), gcc-4.0 (mà tôi đã sử dụng để biên dịch thư viện GSL dưới dạng 32 bit), GSL 1.15 và Cython v0.15.1.

Dưới đây là nội dung của cgibbs.pyx:

#declaring external GSL functions to be used 
cdef extern from "math.h": 
    double sqrt(double) 

cdef double Sqrt(double n): 
    return sqrt(n) 

cdef extern from "gsl/gsl_rng.h": 
    ctypedef struct gsl_rng_type: 
     pass 
    ctypedef struct gsl_rng: 
     pass 
    gsl_rng_type *gsl_rng_mt19937 
    gsl_rng *gsl_rng_alloc(gsl_rng_type * T) 

cdef extern from "gsl/gsl_randist.h": 
    double gamma "gsl_ran_gamma"(gsl_rng * r,double,double) 
    double gaussian "gsl_ran_gaussian"(gsl_rng * r,double) 


cdef gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937) 

Các lỗi sẽ biến mất nếu tôi nhận xét ra dòng cuối cùng của cgibbs.pyx của tôi, nhưng sau đó tôi không thể thực sự sử dụng thư viện bên ngoài ... Bất kỳ cái nhìn sâu sắc mà bạn có thể cung cấp được đánh giá cao. Cảm ơn!

Trả lời

4

Nhờ @ChuiTey, tôi phát hiện ra rằng otoolnm là các công cụ trên Mac có thể thực hiện những gì objdump thực hiện trên Linux. Với nm Tôi thấy rằng dấu gạch dưới hàng đầu là một phần của tên biểu tượng trong thư viện libgsl.a.

Khi tôi biết rằng trình liên kết (trong trường hợp của tôi là ld) đang tìm kiếm đúng tên, rõ ràng là nó không tìm đúng nơi. Và đó là cách tôi học được rằng các tệp tiêu đề không biết vị trí của các thư viện mà chúng liên kết (Duh!) Tôi chỉ cần thêm tùy chọn -lgsl vào lệnh chạy trình liên kết (điều này yêu cầu rằng libgsl.a nằm trong thư mục linker của bạn tìm thư viện - trên máy của tôi, đó là /usr/local/lib.)

Tôi cũng phải di chuyển libgsl.dylib từ /usr/local/lib vì nó được biên dịch cho nền tảng 64 bit và tôi đang sử dụng Python 32 bit.

Phải có cách dễ dàng để chỉ định tùy chọn trình liên kết -lgsl khi biên dịch mã Cython với các đường rãnh hoặc một tệp makefile; cho bây giờ tôi chỉ đang chạy gcc-4.0 hai lần để biên dịch và sau đó liên kết các mô-đun. quy trình làm việc của tôi để biên dịch một module Cython từ dòng lệnh bash là:

cython cgibbs.pyx 
gcc-4.0 -m32 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c cgibbs.c -o cgibbs.o 
gcc-4.0 -bundle -undefined dynamic_lookup -lgsl -arch i386 -g cgibbs.o -o cgibbs.so 

nào sản xuất cgibbs.so, một module Cython có thể được nhập khẩu bằng Python 2.7.

2

Việc thêm một dấu gạch dưới vào các hàm được xuất được gọi là name mangling. Trên Windows, quy ước cdecl gắn thêm một dấu gạch dưới (các quy ước khác có các lược đồ phức tạp hơn).

Có thể bạn chưa chỉ định quy ước gọi điện chính xác khi xây dựng thư viện GSL của mình. Bạn có thể xem tên được xuất bằng cách sử dụng objdump.

GSL đã cung cấp trình bao bọc SWIG chưa?

+0

Tôi không biết từ SWIG - có lẽ tôi nên, mặc dù. – Wesley

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