Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
100644 237 lines (180 sloc) 10.049 kb
4b34bad @jnthn Turn README into Markdown; start to improve things.
1 # Zavolaj!
3 This module implements native calling support for Rakudo Perl 6. It builds
4 on a set of native calling primitives in NQP, adding mapping of Perl 6
5 signatures and various other traits to make working with native libraries
6 an easier experience.
8 The project name is the Slovak translation of the imperative "call!", to
9 complement Blizkost, a Rakudo-to-Perl-5 integration project.
11 Thanks to NQP's underlying use of the dyncall library, Zavolaj can now
12 support arbitrary signatures.
14 ## Getting Started
15 The simplest imaginable use of Zavolaj would look something like this:
17 use NativeCall;
18 sub some_argless_function() is native('libsomething') { * }
19 some_argless_function();
21 The first line imports various traits and types. The next line looks like
22 a relatively ordinary Perl 6 sub declaration - with a twist. We use the
23 "native" trait in order to specify that the sub is actually defined in a
24 native library. The platform-specific extension (e.g. .so or .dll) will be
25 added for you.
27 The first time you call "some_argless_function", the "libsomething" will be
28 loaded and the "some_argless_function" will be located in it. A call will then
29 be made. Subsequent calls will be faster, since the symbol handle is retained.
31 Of course, most functions take arguments or return values - but everything else
32 that you can do is just adding to this simple pattern of declaring a Perl 6
33 sub, naming it after the symbol you want to call and marking it with the "native"
34 trait.
36 ## Passing and Returning Values
37 Normal Perl 6 signatures and the "returns" trait are used in order to convey
38 the type of arguments a native function expects and what it returns. Here is
39 an example.
41 sub add(int32, int32) returns int32 is native("libcalculator") { * }
43 Here, we have declared that the function takes two 32-bit integers and returns
44 a 32-bit integer. Here are some of the other types that you may pass (this will
45 likely grow with time).
47 int8 (char in C)
48 int16 (short in C)
49 int32 (int in C)
50 int (32- or 64-bit, depends what long means locally)
51 Int (always 64-bit, long long in C)
52 num32 (float in C)
53 num64 (double in C)
54 num (same as num64)
55 Str (C string)
57 Note that the lack of a "returns" trait is used to indicate void return type.
59 For strings, there is an additional "encoded" trait to give some extra hints on
60 how to do the marshalling.
62 sub message_box(Str is encoded('utf8')) is native('libgui') { * }
64 To specify how to marshall string return types, just apply this trait to the
65 routine itself.
67 sub input_box() returns Str is encoded('utf8') is native('libgui') { * }
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
69 Note that a null string can be passed by passing the Str type object; a null
70 return will also be represented by the type object.
4b34bad @jnthn Turn README into Markdown; start to improve things.
81ff0e4 @jnthn Document working with pointers.
72 ## Opaque Pointers
73 Sometimes you need to get a pointer (for example, a library handle) back from a
74 C library. You don't care about what it points to - you just need to keep hold
75 of it. The OpaquePointer type provides for this.
77 sub Foo_init() returns OpaquePointer is native("libfoo") { * }
78 sub Foo_free(OpaquePointer) is native("libfoo") { * }
80 This works out OK, but you may fancy working with a type named something better
81 than OpaquePointer. It turns out that any class with the representation "CPointer"
82 can serve this role. This means you can expose libraries that work on handles
83 by writing a class like this:
85 class FooHandle is repr('CPointer') {
86 # Here are the actual Zavolaj functions.
87 sub Foo_init() returns FooPointer is native("libfoo") { * }
88 sub Foo_free(FooPointer) is native("libfoo") { * }
90 # Here are the methods we use to expose it to the outside world.
91 method new() { Foo_init() }
92 method free() { Foo_free(self) }
93 }
95 Note that the CPointer representation can do nothing more than hold a C pointer.
96 This means that your class cannot have extra attributes. However, for simple
97 libraries this may be a neat way to expose an object oriented interface to it.
99 Of course, you can always have an empty class:
101 class DoorHandle is repr('CPointer') { }
103 And just use the class as you would use OpaquePointer, but with potential for
104 better type safety and more readable code.
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
106 Once again, type objects are used to represent nulls.
108 ## Arrays
109 Zavolaj currently has some basic support for arrays. It is constrained to only
110 working with machine-size integers, doubles and strings at the moment; the sized
111 numeric types, arrays of pointers, arrays of structs and arrays of arrays are in
112 development.
114 Perl 6 arrays, which support amongst other things laziness, are laid out in memory
115 in a radically different way to C arrays. Therefore, the NativeCall library offers
116 a much more primitive CArray type, which you must use if working with C arrays.
118 Here is an example of passing a C array.
120 sub RenderBarChart(Str, int, CArray[Str], CArray[num]) is native("libchart") { * }
121 my @titles := CArray[Str].new();
122 @titles[0] = 'Me';
123 @titles[1] = 'You';
124 @titles[2] = 'Your Mom';
125 my @values := CArray[num].new();
126 @values[0] = 59.5e0;
127 @values[1] = 61.2e0;
128 @values[2] = 120.7e0;
129 RenderBarChart('Weights (kg)', 3, @titles, @values);
131 Note that binding was used to @titles, *NOT* assignment! If you assign, you
132 are putting the values into a Perl 6 array, and it will not work out. If this
133 all freaks you out, forget you ever knew anything about the "@" sigil and just
134 use "$" all the way when using Zavolaj. :-)
fdf8cff @jnthn Fix example to show what I'd intended; tadzik++ for noticing.
136 my $titles = CArray[Str].new();
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
137 $titles[0] = 'Me';
138 $titles[1] = 'You';
139 $titles[2] = 'Your Mom';
141 Getting return values for arrays works out just the same.
143 The memory management of arrays is important to understand. When you create an
144 array yourself, then you can add elements to it as you wish and it will be
145 expanded for you as required. However, this may result in it being moved in
146 memory (assignments to existing elements will never cause this, however). This
147 means you'd best know what you're doing if you twiddle with an array after passing
148 it to a C library.
150 By contrast, when a C library returns an array to you, then the memory can not
151 be managed by Zavolaj, and it doesn't know where the array ends. Presumably,
152 something in the library API tells you this (for example, you know that when
153 you see a null element, you should read no further). Note that Zavolaj can offer
154 you no protection whatsoever here - do the wrong thing, and you will get a
155 segfault or cause memory corruption. This isn't a shortcoming of Zavolaj, it's
156 the way the big bad native world works. Scared? Here, have a hug. Good luck! :-)
158 ## Structs
159 Thanks to representation polymorphism, it's possible to declare a normal looking
160 Perl 6 class that, under the hood, stores its attributes in the same way a C
161 compiler would lay them out in a similar struct definition. All it takes is a
162 quick use of the "repr" trait:
164 class Point is repr('CStruct') {
165 has num64 $.x;
166 has num64 $.y;
167 }
169 The attributes can only be of the types that Zavolaj knows how to marshall into
5c2a473 @arnsholt Update the README to reflect the new struct reality.
arnsholt authored
170 struct fields. Currently, structs can contain machine-sized integers, doubles,
16af23b @moritz fix typo
moritz authored
171 strings, and other Zavolaj objects (CArrays, and those using the CPointer and
5c2a473 @arnsholt Update the README to reflect the new struct reality.
arnsholt authored
172 CStruct reprs). Other than that, you can do the usual set of things you would with
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
173 a class; you could even have some of the attributes come from roles or have them
174 inherited from another class. Of course, methods are completely fine too. Go wild!
176 The memory management rules are very much like for arrays, though simpler since a
177 struct is never resized. When you create a struct, the memory is managed for you and
178 when the variable(s) pointing to the instance of a CStruct go away, the memory will
179 be freed when GC gets to it. When a CStruct-based type is used for the return type,
180 the memory is not managed for you.
5c2a473 @arnsholt Update the README to reflect the new struct reality.
arnsholt authored
182 Zavolaj currently doesn't put object members in containers, so assigning new values
183 to them (with =) doesn't work. Instead, you have to bind new values to the private
184 members: $!struct-member :=;
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
186 As you may have predicted by now, a null is represented by the type object of the
187 struct type.
189 ## The Future
190 See the TODO file. In general, though, it's mostly about making arrays and structs
191 much more capable, providing more options for memory management and supporting
192 callbacks. Something missing that's blocking you? Talk to jnthn on #perl6 - the
193 TODO list can be shuffled around to suit what potential users are after. Or just
194 send in a patch. ;-)
81ff0e4 @jnthn Document working with pointers.
4b34bad @jnthn Turn README into Markdown; start to improve things.
196 ## Running the Examples
198 The examples directory contains various examples of how to use Zavolaj.
d9250b0 @moritz remove segfaulting sqlite example, point to working DBDish/*.pm6 modules...
moritz authored
200 More examples can be found in the lib/DBDish/ directory of the DBIsh repository
201 at
4b34bad @jnthn Turn README into Markdown; start to improve things.
203 ### MySQL
205 There is an exmaple of using the MySQL client library. There is a Rakudo project
206 that wraps these functions with a DBI
207 compatible interface. You'll need that library to hand; on Debian-esque systems
208 it can be installed with something like:
210 sudo apt-get install libmysqlclient-dev
212 Prepare your system along these lines before trying out the examples:
214 $ mysql -u root -p
215 CREATE DATABASE zavolaj;
216 CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpass';
217 GRANT CREATE ON zavolaj.* TO 'testuser'@'localhost';
218 GRANT DROP ON zavolaj.* TO 'testuser'@'localhost';
219 GRANT INSERT ON zavolaj.* TO 'testuser'@'localhost';
220 GRANT DELETET ON zavolaj.* TO 'testuser'@'localhost';
221 GRANT SELECT ON zavolaj.* TO 'testuser'@'localhost';
222 GRANT LOCK TABLES ON zavolaj.* TO 'testuser'@'localhost';
223 GRANT SELECT ON mysql.* TO 'testuser'@'localhost';
224 # or maybe otherwise
225 GRANT ALL PRIVILEGES ON zavolaj.* TO 'testuser'@'localhost';
227 You can look at the results via a normal mysql connection:
229 $ mysql -utestuser -ptestpass
230 USE zavolaj;
232 SELECT * FROM nom;
e8e83dc @jnthn First crack at documenting array and struct usage with Zavolaj.
234 ### Microsoft Windows
4b34bad @jnthn Turn README into Markdown; start to improve things.
236 The win32-api-call.p6 script shows a Windows API call done from Perl 6.
Something went wrong with that request. Please try again.