Skip to content

Commit 527e593

Browse files
committed
Document FFI library
1 parent 427945e commit 527e593

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed

docs/Runtime Environment/FFI.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
Must be included via `require`.
2+
3+
:::caution
4+
This is intended for advanced users.
5+
:::
6+
7+
---
8+
### `ffi.open`
9+
Loads a DLL/SO (dynamic link library/shared object).
10+
#### Parameters
11+
1. The name of the library which is to be located by the operating system. A relative or absolute path also works.
12+
#### Returns
13+
An FFI library instance.
14+
#### Example
15+
The following C++ code:
16+
```cpp title="lib.cpp"
17+
#ifdef _WIN32
18+
#define EXPORT __declspec(dllexport)
19+
#else
20+
#define EXPORT
21+
#endif
22+
23+
extern "C" EXPORT int MY_MAGIC_INT = 69;
24+
25+
extern "C" EXPORT int add(int a, int b) {
26+
return a + b;
27+
}
28+
```
29+
Compiled like this:
30+
- Windows: `clang -std=c++17 --shared -o lib.dll lib.cpp`
31+
- Linux/MacOS: `clang -std=c++17 --shared -o liblib.so lib.cpp`
32+
33+
Can be used like this:
34+
```pluto
35+
local ffi = require "pluto:ffi"
36+
local lib = ffi.open(os.platform == "windows" ? "lib" : "./liblib.so")
37+
assert(lib:value("i32", "MY_MAGIC_INT") == 69)
38+
assert(lib:wrap("i32", "add", "i32", "i32")(38, 4) == 42)
39+
```
40+
---
41+
### `ffi.struct`
42+
Parses a subset of C for a struct.
43+
#### Paramters
44+
1. The C source code.
45+
#### Returns
46+
An FFI Struct Type instance.
47+
#### Example
48+
```pluto
49+
local ffi = require "pluto:ffi"
50+
51+
local Color = ffi.struct[[
52+
struct Color {
53+
uint8_t r;
54+
uint8_t g;
55+
uint8_t b;
56+
};
57+
]]
58+
59+
local c = new Color()
60+
c.r = 255
61+
print(c.r) --> 255
62+
```
63+
64+
---
65+
### `ffi.new`
66+
Instantiate an FFI Struct Type by name or instance.
67+
#### Parameters
68+
1. An FFI Struct Type instance or the name of one stored on the FFI library itself.
69+
#### Returns
70+
A new instance of the struct.
71+
72+
---
73+
### `ffi.cdef`
74+
Parses a subset of C for structs to be stored on the FFI library itself.
75+
#### Parameters
76+
1. The C source code.
77+
#### Example
78+
```pluto
79+
local ffi = require "pluto:ffi"
80+
81+
ffi.cdef[[
82+
struct Color {
83+
uint8_t r;
84+
uint8_t g;
85+
uint8_t b;
86+
};
87+
]]
88+
89+
local c = ffi.new("Color")
90+
c.r = 255
91+
print(c.r) --> 255
92+
```
93+
94+
---
95+
### `ffi.sizeof`
96+
Measures the size of an FFI Struct Type.
97+
#### Parameters
98+
1. An FFI Struct Type instance, the name of a struct stored on the FFI library itself, or an instance of the struct.
99+
#### Returns
100+
The size in bytes.
101+
102+
---
103+
### `ffi.offsetof`
104+
Measures the offset of a field on an FFI Struct Type.
105+
#### Parameters
106+
1. An FFI Struct Type instance, the name of a struct stored on the FFI library itself, or an instance of the struct.
107+
2. The name of the field.
108+
#### Returns
109+
The offset in bytes.
110+
111+
---
112+
### `ffi.nullptr`
113+
This constant can be used to give `0` to a "ptr"-type argument.
114+
115+
---
116+
## FFI Library Class
117+
Obtained from `ffi.open`.
118+
119+
### `wrap`
120+
Creates a function wrapper.
121+
#### Parameters
122+
1. The return type. Can be "void", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "ptr" or "str".
123+
2. The name of the function.
124+
3. The argument type(s). Can be "void", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "ptr" or "str".
125+
#### Returns
126+
A new function wrapper instance, which can be called.
127+
128+
### `value`
129+
Gets an exported value and interprets it using the given type.
130+
#### Parameters
131+
1. The type. Can be "void", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "ptr" or "str".
132+
2. The name of the export.
133+
#### Returns
134+
The interpreted value.
135+
136+
### `cdef`
137+
Parses a subset of C for values and functions and puts them on the library instance.
138+
#### Parameters
139+
1. The C source code.
140+
#### Example
141+
```pluto
142+
local ffi = require "pluto:ffi"
143+
local lib = ffi.open(os.platform == "windows" ? "lib" : "./liblib.so")
144+
lib:cdef[[
145+
int MY_MAGIC_INT;
146+
int add(int a, int b);
147+
]]
148+
assert(lib.MY_MAGIC_INT == 69)
149+
assert(lib.add(38, 4) == 42)
150+
```
151+
This is equivalent to the following:
152+
```pluto
153+
local ffi = require "pluto:ffi"
154+
local lib = ffi.open(os.platform == "windows" ? "lib" : "./liblib.so")
155+
156+
lib.MY_MAGIC_INT = lib:value("i32", "MY_MAGIC_INT")
157+
lib.add = lib:wrap("i32", "add", "i32", "i32")
158+
159+
assert(lib.MY_MAGIC_INT == 69)
160+
assert(lib.add(38, 4) == 42)
161+
```

docusaurus.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const config = {
4747
{
4848
theme: 'monokai-patched',
4949
langs: [
50+
'c',
5051
'cpp',
5152
{
5253
id: 'pluto',

src/theme/Pluto.tmLanguage.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,32 @@
147147
"match": "\\)",
148148
"name": "punctuation.section.group.end.pluto"
149149
},
150+
{
151+
"begin": "(?<=[\\.\\:]cdef|ffi\\.struct)\\s*(\\[(=*)\\[)",
152+
"beginCaptures": {
153+
"0": {
154+
"name": "string.quoted.other.multiline.pluto"
155+
},
156+
"1": {
157+
"name": "punctuation.definition.string.begin.pluto"
158+
}
159+
},
160+
"contentName": "meta.embedded.pluto",
161+
"end": "(\\]\\2\\])",
162+
"endCaptures": {
163+
"0": {
164+
"name": "string.quoted.other.multiline.pluto"
165+
},
166+
"1": {
167+
"name": "punctuation.definition.string.end.pluto"
168+
}
169+
},
170+
"patterns": [
171+
{
172+
"include": "source.c"
173+
}
174+
]
175+
},
150176
{
151177
"begin": "(?<!--)\\[(=*)\\[",
152178
"beginCaptures": {

0 commit comments

Comments
 (0)