2017-04-12 18 views
5

Tôi đang làm việc với giao diện NativeCall.Làm thế nào tôi có thể vượt qua một đối tượng Perl 6 thông qua một cuộc gọi lại Nativecall?

Thư viện sẽ gọi hàm gọi lại của tôi nhiều lần.

Điều đó hoạt động tốt. Tôi chỉ có thể khai báo cuộc gọi lại của mình với chữ ký đúng, chuyển nó thành số & gọi lại và thư viện gọi điện cho tiểu chỉ là .

Nó cũng có khả năng đặt con trỏ void * tải trọng thành bất kỳ thứ gì Tôi muốn và nó sẽ bao gồm trong cuộc gọi đến hàm gọi lại của tôi.

Tôi có thể ẩn một đường Perl, ví dụ, trong tải trọng và chuyến đi khứ hồi thành công không?

sub set_userdata(Pointer) returns int32 is native { ... } 

sub set_callback(&callback(Pointer $userdata --> int32)) returns int32 is native { ... } 

sub callback(Pointer $userdata) returns int32 { 
    my Str $mystring = ??? 
    ... 
} 

my Str $my-userdata-string; 

set_userdata(???); 
set_callback(&callback); 

Dường như nó có thể hoạt động với một số câu thần chú ràng buộc, "là rw", nativecast() và/hoặc .deref.

Trả lời

2

Tôi đã giải quyết vấn đề này bằng cách bỏ qua userdata và tạo một kết thúc mới tham chiếu đối tượng Perl trực tiếp cho mọi chức năng gọi lại. Vì có một đóng cửa mới được tạo ra mỗi khi tôi thiết lập gọi lại, tôi nghĩ rằng điều này sẽ bị rò rỉ bộ nhớ theo thời gian.

+2

Mặc dù Jonathan Worthington đưa ra một cách tiếp cận tốt hơn, tôi nghĩ rằng một ví dụ rút gọn về nỗ lực của bạn sẽ được mát mẻ để xem trong câu trả lời này, như mọi người có thể thảo luận nếu giải pháp của bạn có giá trị, và nếu nó thực sự bị rò rỉ bộ nhớ. Đây là một trang web học tập sau khi tất cả. –

7

Bạn chỉ có thể sử dụng đại diện gốc trong trường hợp như vậy (chẳng hạn như CStruct, CArrayCPointer), hoặc cách khác là Blob. Bạn cũng chịu trách nhiệm đảm bảo rằng bạn giữ một tham chiếu đến điều bạn vượt qua như là userdata còn sống từ góc nhìn của Perl 6, vì vậy GC không đòi lại bộ nhớ đã được chuyển cho hàm C.

Quản lý bộ nhớ là lý do bạn không thể chuyển bất kỳ đối tượng Perl 6 cũ nào sang hàm C: không có cách nào để GC biết liệu đối tượng vẫn có thể truy cập được thông qua một số cấu trúc dữ liệu C không thể quan sát được. Trong một máy ảo như các đối tượng MoarVM được di chuyển xung quanh trong bộ nhớ theo thời gian như là một phần của quá trình thu gom rác, có nghĩa là mã C có thể kết thúc bằng một con trỏ đã lỗi thời.

Một chiến lược thay thế không phải là không vượt qua một con trỏ ở tất cả, nhưng thay vì vượt qua một số nguyên và sử dụng nó để lập chỉ mục vào một mảng các đối tượng. (Đó là cách libuv ràng buộc bên trong của MoarVM theo dõi các cuộc gọi lại VM-level, fwiw.)

+0

Tôi thích ý tưởng chỉ mục thành một mảng tĩnh mà tôi quản lý ở bên Perl. Sau đó, một cuộc gọi lại chỉ có thể lấy đúng đối tượng với điều đó. Cảm ơn! –

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