Phần mở rộng riêng của ngôn ngữ script - tránh xung đột tên và làm lộn xộn không gian tên của người khác


8

Tôi đã phát triển một ngôn ngữ kịch bản nhỏ và tôi mới bắt đầu viết các ràng buộc thư viện riêng đầu tiên. Đây thực tế là lần đầu tiên tôi viết một phần mở rộng riêng cho ngôn ngữ kịch bản, vì vậy tôi gặp phải một vấn đề về khái niệm.

Tôi muốn viết mã keo cho các thư viện phổ biến để có thể sử dụng chúng từ ngôn ngữ này và do thiết kế của công cụ tôi đã viết, điều này đạt được bằng cách sử dụng một mảng C structmô tả tên hàm có thể nhìn thấy bởi máy ảo, cùng với một con trỏ hàm.

Do đó, một ràng buộc riêng thực sự chỉ là một biến toàn cục và bây giờ tôi rõ ràng phải đặt cho nó một cái tên (tốt nhất là tốt). Trong C, thật đơn giản để đặt các hàm riêng của mình vào một "không gian tên" bằng cách thêm tiền tố tùy chỉnh vào tên hàm, như trong myscript_parse_source()hoặc myscript_run_bytecode(). Tên tùy chỉnh sẽ mô tả lý tưởng tên của thư viện mà nó là một phần của. Ở đây phát sinh sự nhầm lẫn.

Hãy nói rằng tôi đang viết một ràng buộc cho libcURL. Trong trường hợp này, có vẻ hợp lý khi gọi thư viện mở rộng của tôi curl_myscript_binding, như thế này:

MYSCRIPT_API const MyScriptExtFunc curl_myscript_lib[10];

Nhưng bây giờ điều này va chạm với curlkhông gian tên. (Tôi thậm chí đã nghĩ đến việc gọi nó curlmyscript_libnhưng thật không may, libcURL không chỉ sử dụng curl_tiền tố - các API công cộng có chứa các macro như CURLCODE_*CURLOPT_*vì vậy tôi cho rằng điều này cũng sẽ làm lộn xộn không gian tên.)

Một lựa chọn khác là khai báo nó myscript_curl_lib, nhưng điều đó chỉ tốt khi tôi là người duy nhất viết các ràng buộc (vì tôi biết tôi đang làm gì với không gian tên của mình). Ngay khi những người đóng góp khác bắt đầu thêm các ràng buộc riêng của họ, bây giờ họ làm lộn xộn myscriptkhông gian tên. (Tôi đã thực hiện một số nghiên cứu và có vẻ như ví dụ ràng buộc Perl cURL tuân theo mô hình này. Không chắc tôi nên nghĩ gì về điều đó ...)

Vì vậy, làm thế nào để bạn đề nghị tôi đặt tên biến của tôi? Có hướng dẫn chung nào cần được tuân theo không?


3
Không cần thiết cho toàn cầu. Bạn cũng có thể cung cấp một chức năng trong API của mình để đăng ký một tiện ích mở rộng mới, ví dụ: SomeLang_register_extension("curl", "H2CO3", "000.001.000", the_extension)nơi the_extensionchỉ đến một số cấu trúc tiện ích mở rộng nhưng không hiển thị trên toàn cầu. Ngôn ngữ của bạn sau đó sẽ giữ cấu trúc dữ liệu nội bộ để sắp xếp các phần mở rộng theo tên, phiên bản và tác giả.
amon

@amon Chắc chắn, điều đó cũng có thể.
H2CO3

Câu trả lời này có thể được quan tâm, nó liên quan đến một chủ đề khác nhưng nó giải thích cách các quy ước đặt tên được bắt nguồn cho HTML; có các quy tắc tương tự cho các ngôn ngữ khác nhau, có thể hữu ích khi chọn một quy ước phù hợp với nhu cầu của bạn và tuân theo nó.
Rob

Câu trả lời:


2

Thực tế, không cần thiết phải chứa một loạt các hàm xuất khẩu toàn cầu chỉ để làm cho chúng hiển thị với môi trường thời gian chạy của bạn.

Một câu hỏi hay được đặt ra là liệu môi trường thời gian chạy của bạn có lưu con trỏ hàm và tên liên quan đến nó không?

Ý tưởng của bạn về việc sử dụng một mảng toàn cục để xuất các hàm chỉ có ý nghĩa nếu môi trường thời gian chạy của bạn không lưu thông tin đó nhưng tôi cho rằng bạn phải lưu nó để môi trường thực thi của VM thực thi đúng.

Một tính năng phổ biến được thêm vào ngôn ngữ kịch bản như của bạn là ý tưởng đăng ký các chức năng của bạn .

Về cơ bản, bạn cần một phương tiện để lưu trữ ptr của hàm đã xuất và tên của con trỏ hàm đã xuất sẽ được sử dụng trong mã tập lệnh.

Tôi biết hai tùy chọn bạn có thể thực hiện cho việc này:

  1. Một hashmap sẽ sử dụng tên hàm phía tập lệnh làm khóa chuỗi và ptr của hàm làm giá trị được liên kết với khóa đó.

    exported_funcs["do_thing"] = &native_do_thing;

  2. Thường được sử dụng trong các ngôn ngữ kịch bản hệ thống nhúng như Pawn, bạn có thể sử dụng chính dữ liệu tập lệnh để lưu trữ con trỏ hàm. Khi bạn "đăng ký" hàm, bạn lặp lại bảng hàm xuất của tập lệnh và tìm kiếm tên mà hàm đã xuất sẽ đăng ký là; một khi bạn tìm thấy tên đó, ghi đè lên dữ liệu tập lệnh đó (không phải chính tệp tập lệnh mà là dữ liệu bộ nhớ tập lệnh đã tải) và về cơ bản bạn đã lưu trữ con trỏ hàm gốc.

FuncPtrType **table_entry = get_script_entry_ptr(func_name); *table_entry = func_ptr;

Tôi đặc biệt khuyên rằng, đối với tùy chọn thứ 2, bạn cung cấp cho mục nhập bảng đủ kích thước để chứa kích thước con trỏ của tất cả các kiến ​​trúc, đáng chú ý là mục nhập phải là 8 byte.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.