2013-08-17 28 views
10

Tôi có một thư viện gốc mà giao diện tự nhiên sẽ bao gồm việc truyền các số có khả năng lớn. Tôi dự đoán khoảng một nửa là < 32 bit; một quý khác < 64 bit; tiếp theo là < 128 bit - và cứ thế, không có giới hạn độ dài cố định.Mở rộng Python - xây dựng và kiểm tra các số nguyên lớn hiệu quả

PyLong_FromUnsignedLongLong() và PyLong_AsUnsignedLongLong() sẽ phù hợp nếu tôi có thể hạn chế các giá trị vừa với một thanh ghi duy nhất.

PyLong_FromString() vượt qua điều này - nhưng với chi phí không mong muốn yêu cầu đại diện trung gian. _PyLong_FromByteArray() và _PyLong_AsByteArray() giảm thiểu chi phí này (bằng cách làm cho biểu diễn trung gian này đơn giản) nhưng dấu gạch dưới hàng đầu khiến tôi tự hỏi liệu điều này có thể dẫn đến các vấn đề về tính di động hay không.

Trong longintrepr.h, tôi đã tìm thấy struct _longobject ... gợi ý rằng nó có thể là một cách tương tác trực tiếp với biểu diễn bên trong ... mặc dù thiếu tài liệu chi tiết về cấu trúc này vẫn là một trở ngại.

Cách tiếp cận nào sẽ dẫn đến thông lượng tối ưu giữa Python và thư viện? Có tài liệu nào tôi đã bỏ qua không?

+2

Sau đó, áp dụng API nhanh cho những con số đủ nhỏ và "PyLong_FromString" chỉ cho những số lớn, hoặc không đủ nhanh ?. (Nhân tiện, bạn có lẽ nên gắn thẻ câu hỏi của bạn với 'python-c-api') – dastrobu

+3

Bạn có hồ sơ * và * thấy rằng chuyển đổi là một nút cổ chai hay bạn chỉ đơn giản là suy đoán? Trước khi tìm một giải pháp phức tạp cho một vấn đề đơn giản, hãy chắc chắn rằng có * là * một vấn đề. – Bakuriu

+0

Mối quan tâm của tôi ở giai đoạn thiết kế API, không phải là kết quả của việc lập hồ sơ triển khai. Tôi đang tìm phương pháp gọn gàng nhất của (A) xây dựng các đối tượng PyLong trong C - nơi tôi biết chiều dài của chúng và bit nào được thiết lập; và (B) so sánh và kiểm tra các bit trong các đối tượng PyLong từ C. Chuỗi liên quan ở tất cả dường như rất clunky, tôi hy vọng sẽ tìm thấy một giải pháp neater. – aSteve

Trả lời

7

Tiền tố gạch dưới phần lớn có nghĩa là cùng một điều trong API C như trong Python bình thường: "chức năng này là chi tiết triển khai có thể thay đổi, vì vậy hãy xem bản thân nếu bạn sử dụng nó". Bạn không bị cấm sử dụng các chức năng như vậy và nếu đó là cách duy nhất để đạt được mục tiêu cụ thể (ví dụ: tăng hiệu quả đáng kể trong trường hợp của bạn), thì bạn nên sử dụng API miễn là bạn biết về mối nguy.

Nếu API _PyLong_FromByteArray thực sự riêng tư, nó sẽ là một hàm static và sẽ không được ghi chép đầy đủ và xuất trong longobject.h. Trong thực tế, Tim Peters (một nhà phát triển cốt lõi Python nổi tiếng) một cách rõ ràng blesses its use:

[Dan Christensen]

sinh viên của tôi và tôi đang viết một phần mở rộng C mà tạo ra một số nguyên lớn trong hệ nhị phân mà chúng tôi muốn chuyển đổi thành một con trăn dài. Số bit của có thể nhiều hơn 32 hoặc thậm chí 64. Học sinh của tôi tìm thấy hàm _PyLong_FromByteArray trong longobject.h, chính xác là những gì chúng ta cần, nhưng dấu gạch dưới hàng đầu làm cho tôi cảnh giác. Có an toàn để sử dụng chức năng này không?

Python sử dụng nó trong nội bộ, vì vậy nó tốt hơn được ;-)

Nó sẽ tiếp tục tồn tại trong các phiên bản tương lai của python?

Không bảo lãnh, và đó là lý do tại sao nó có một dấu gạch dưới hàng đầu: nó không phải là một hỗ trợ chính thức, bên ngoài ghi nhận, một phần của quảng cáo Python/C API. Điều đó xảy ra là tôi đã thêm chức năng đó, bởi vì Python cần một số chức năng của nó trong nội bộ qua các mô-đun C khác nhau trong số .Làm cho nó một phần chính thức của Python/C API sẽ có được nhiều công việc hơn (mà tôi không có thời gian cho), và tạo ra một gánh nặng bảo trì vĩnh cửu mới (mà tôi không quan tâm trên bất kể; -)).

Trong thực tế, ít người chạm vào phần này của việc triển khai Python, vì vậy Tôi không/mong đợi/nó sẽ biến mất, hoặc thậm chí thay đổi, trong nhiều năm tới. Sự bất an lớn nhất mà tôi có thể nghĩ là một ai đó có thể khởi động một cuộc thập tự chinh để làm cho một số byte khác là < -> giao diện dài "chính thức" dựa trên một cách khác để biểu diễn các số nguyên âm. Nhưng thậm chí sau đó tôi mong đợi các chức năng không chính thức hiện tại vẫn còn, vì biểu diễn bổ sung của 256 vẫn cần thiết cho định dạng "q" của struct của mô-đun và đối với định dạng nối tiếp dàicủa mô-đun = 2 .

Hoặc có phương pháp nào khác mà chúng ta nên sử dụng không?

số Đó là lý do các chức năng này đã được phát minh để bắt đầu với ;-)

Đây là tài liệu hướng dẫn (từ Python 3.2.1):

/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in 
    base 256, and return a Python long with the same numeric value. 
    If n is 0, the integer is 0. Else: 
    If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; 
    else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the 
    LSB. 
    If is_signed is 0/false, view the bytes as a non-negative integer. 
    If is_signed is 1/true, view the bytes as a 2's-complement integer, 
    non-negative if bit 0x80 of the MSB is clear, negative if set. 
    Error returns: 
    + Return NULL with the appropriate exception set if there's not 
    enough memory to create the Python long. 
*/ 
PyAPI_FUNC(PyObject *) _PyLong_FromByteArray(
    const unsigned char* bytes, size_t n, 
    int little_endian, int is_signed); 

Lý do chính nó là một " API "tiền tố" là bởi vì nó phụ thuộc vào việc triển khai Python long dưới dạng một mảng các từ trong cơ sở lũy thừa hai. Điều này không có khả năng thay đổi, nhưng vì bạn đang triển khai một API trên đầu trang này, bạn có thể cách ly người gọi của bạn từ những thay đổi trong Python API sau này.

+0

Thông tin rất hữu ích về phương pháp _PyLong_FromByteArray() .Tôi vẫn muốn thiết lập nếu có một cách tiếp cận khả thi tương tự thậm chí còn trực tiếp hơn.Tôi có thể đi qua một mảng byte (theo cả hai hướng) nhưng tôi muốn tương tác trực tiếp với một mảng "chân tay" - theo cách tương tự khi sử dụng GMP/MPIR - đặc biệt khi đọc các số nguyên lớn trong C. – aSteve

+0

@ aSteve: Không phải không sử dụng API riêng tư hơn nữa, tôi sợ. 'longintrepr.h' định nghĩa' struct _longobject', và có một khối tài liệu lớn đẹp ngay phía trên nó. Phần duy nhất có thể trông lạ là 'PyObject_VAR_HEAD', được [tài liệu] (http://docs.python.org/release/3.0/c-api/structures.html#PyObject_VAR_HEAD). Tất nhiên, nếu bạn thực sự sử dụng 'longintrepr.h', bạn có trách nhiệm theo kịp bất kỳ và tất cả các lỗi API có thể xảy ra. – nneonneo

0

Có vẻ như bạn cần PyNumber_Long. Một số lần truy cập tài liệu là here.

+0

Tôi tin rằng OP muốn chuyển đổi giữa người bản địa Các kiểu C và các đối tượng python, do đó anh ta không thể sử dụng 'PyNumber_Long' – Bakuriu

+0

Tôi đã tìm thấy Python" Number Protocol "- cung cấp các số thường xuyên trên các số python dài ... nhưng tôi không thấy bất kỳ chức năng nào giúp tôi xây dựng hiệu quả/kiểm tra các đối tượng này từ C. – aSteve

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