You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* redo pointer reading
pointers dont deref themselves
memcpy accepts all ffi types, even other pointers
pointers know their type
* setting mostly works, minor bugs
* get arrays to work
* repr structs
* get return types working properly
* get length indices working
* check for duplicate indices
* get out parameters working
* format array structs better
* add more type aliases
* optimize pointer reading
* chnage type display
* update ffi documentation
* make ffi tests pass
* add to changelog
* Fix woring in the changlog
Co-authored-by: Omnikar <[email protected]>
---------
Co-authored-by: Omnikar <[email protected]>
Copy file name to clipboardExpand all lines: changelog.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,7 @@ This version is not yet released. If you are reading this on the website, then t
14
14
-**Breaking Change** - [`under ⍜`](https://uiua.org/docs/under)[`shape △`](https://uiua.org/docs/shape) now tiles the original array to match the new shape instead of [`reshape ↯`](https://uiua.org/docs/reshape)ing
15
15
-**Breaking Change** - [`dip ⊙`](https://uiua.org/docs/dip) and [`on ⟜`](https://uiua.org/docs/on) function packs no longer apply their modifier to the leftmost function
16
16
- This change makes most usecases of these function packs cleaner, as `A⊙(B|C)` changes to `⊙(A|B|C)` and likewise for [`on ⟜`](https://uiua.org/docs/on)
17
+
-**Breaking Change** - The FFI function API has been changed considerably, read more in the documentation for [`&ffi`](https://uiua.org/docs/&ffi), [`&memcpy`](https://uiua.org/docs/&memcpy), and [`&memset`](https://uiua.org/docs/&memset)
17
18
- Allow for private [modules](https://uiua.org/tutorial/modules#private-scoped-modules), [imports](https://uiua.org/tutorial/modules#private-imports), and [data definitions](https://uiua.org/tutorial/datadefs#visibility)
18
19
- Add array pack syntactic sugar. This lets you write code like `[⊃(+|×)]` as `⊃[+|×]`.
19
20
- Subscripts can now be typed with `,` instead of `__`s
Copy file name to clipboardExpand all lines: parser/src/defs.rs
+20-23Lines changed: 20 additions & 23 deletions
Original file line number
Diff line number
Diff line change
@@ -3998,8 +3998,10 @@ sys_op! {
3998
3998
/// - `unsigned int`
3999
3999
/// - `unsigned long`
4000
4000
/// - `unsigned long long`
4001
+
/// Any unsigned type can be written with just a `u` such as `uint` instead of `unsigned int`.
4001
4002
/// Suffixing any of these with `*` makes them a pointer type.
4002
4003
/// Struct types are defined as a list of types between `{}`s separated by `;`s, i.e. `{int; float}`. A trailing `;` is optional.
4004
+
/// A struct with all fields of the same type can be written like `type[number]`. For example a pair of `int`s would be written `int[2]`.
4003
4005
///
4004
4006
/// Arguments are passed as a list of boxed values.
4005
4007
/// If we have a C function `int add(int a, int b)` in a shared library `example.dll`, we can call it like this:
@@ -4011,32 +4013,25 @@ sys_op! {
4011
4013
/// Uiua arrays can be passed to foreign functions as pointer-length pairs.
4012
4014
/// To do this, specify the type of the list items followed by `:n`, where `n` is the index of the parameter that corresponds to the length.
4013
4015
/// The interpreter will automatically pass the number of elements in the array to this parameter.
4014
-
/// Arrays passed in this way will be implicitely [deshape]ed, unless the item type is a struct.
4015
4016
/// If we wave a C function `int sum(const int* arr, int len)` in a shared library `example.dll`, we can call it like this:
4016
4017
/// ex! # Experimental!
4017
4018
/// : Lib ← &ffi ⊂□"example.dll"
4018
-
/// : Sum ← Lib {"int" "sum" "const int:1" "int"}
4019
+
/// : Sum ← Lib {"int" "sum" "int:1" "int"}
4019
4020
/// : Sum {[1 2 3 4 5]} # 15
4020
4021
///
4021
4022
/// [&ffi] calls can return multiple values.
4022
-
/// In addition to the return value, any non-`const` pointer parameters will be interpreted as out-parameters.
4023
+
/// In addition to the return value, any parameters prefixed with `out` will be sent and returned as out parameters.
4024
+
/// If the out parameter is not marked as a pointer, it will be interpreted as a single value, and will be read back into an array when returned.
4025
+
/// If the out parameter is marked as a pointer, it will be interpreted as an array and will be returned as a pointer value. This is allows you to keep memory that is allocated by passing an array valid.
4023
4026
/// If there is more than one output value (including the return value), [&ffi] will return a list of the boxed output values.
4024
-
/// If we have a C function `int split_head(int* list, int* len)` in a shared library `example.dll`, we can call it like this:
/// Note that the length parameter is a non-`const` pointer. This is because the function will modify it.
4030
-
///
4031
-
/// `const char*` parameters and return types are interpreted as null-terminated strings, without an associated length parameter.
4032
4027
///
4033
4028
/// Structs can be passed either as lists of boxed values or, if all fields are of the same type, as a normal array.
4034
4029
/// If all fields of a struct returned by a foreign function are of the same type, the interpreter will automatically interpret it as an array rather than a list of boxed values.
4035
4030
/// If we have a C struct `struct Vec2 { float x; float y; }` and a function `Vec2 vec2_add(Vec2 a, Vec2 b)` in a shared library `example.dll`, we can call it like this:
4036
4031
/// ex! # Experimental!
4037
4032
/// : Lib ← &ffi ⊂□"example.dll"
4038
-
/// : VecII ← "{float; float}"
4039
-
/// : Add ← Lib {VecII "vec2_add" VecII VecII}
4033
+
/// : Vec₂ ← "float[2]"
4034
+
/// : Add ← Lib {Vec₂ "vec2_add" Vec₂ Vec₂}
4040
4035
/// : Add {[1 2] [3 4]} # [4 6]
4041
4036
///
4042
4037
/// If a foreign function returns or has an out-parameter that is a pointer type, a special array is returned representing the pointer. This array is not useful as a normal array, but it can be passed back as an [&ffi] argument, read from with [&memcpy], or freed with [&memfree].
@@ -4052,31 +4047,33 @@ sys_op! {
4052
4047
/// Expects a string indicating the type, a pointer, and a length.
4053
4048
///
4054
4049
/// The returned array will always be rank-`1`.
4055
-
/// The type of the array depends on the given type.
4056
-
/// Types are specified in the same way as in [&ffi].
4057
-
/// `"char"` will create a character array.
4058
-
/// `"unsigned char"` will create a number array with efficient byte storage.
4059
-
/// All other number types will create a normal number array.
4050
+
/// The type of the array depends on the pointer's type.
4060
4051
///
4061
4052
/// For example, if we have a C function `int* get_ints(int len)` in a shared library `example.dll`, we can call it and copy the result like this:
4062
4053
/// ex! # Experimental!
4063
4054
/// : Lib ← &ffi ⊂□"example.dll"
4064
4055
/// : GetInts ← Lib {"int*" "get_ints" "int"}
4065
-
/// : &memcpy "int":3 GetInts 3
4056
+
/// : &memcpy ⊸GetInts 3
4066
4057
///
4067
4058
/// Importantly, [&memcpy] does *not* free the memory allocated by the foreign function.
4068
4059
/// Use [&memfree] to free the memory.
4069
4060
/// ex! # Experimental!
4070
4061
/// : Lib ← &ffi ⊂□"example.dll"
4071
4062
/// : GetInts ← Lib {"int*" "get_ints" "int"}
4072
-
/// : ⊃&memfree(&memcpy "int":3) GetInts 3
4073
-
(3,MemCopy,Ffi,"&memcpy","foreign function interface - copy",Mutating,{ experimental:true}),
4063
+
/// : ⊃&memfree&memcpy ⊸GetInts 3
4064
+
(2,MemCopy,Ffi,"&memcpy","foreign function interface - copy",Mutating,{ experimental:true}),
4065
+
/// Write data from an array into a pointer
4066
+
///
4067
+
/// Expects a pointer, an index, and a value.
4068
+
///
4069
+
/// This function is equivalent to the C syntax `pointer[index] = value`
4070
+
(3(0),MemSet,Ffi,"&memset","write to memory",Mutating,{ experimental:true}),
4074
4071
/// Free a pointer
4075
4072
///
4076
4073
/// *Warning ⚠️: [&memfree] can lead to undefined behavior if used incorrectly.*
4077
4074
///
4078
-
/// This is useful for freeing memory allocated by a foreign function.
4079
-
/// Expects a pointer.
4075
+
/// This is useful for freeing memory allocated by a foreign function, or by an out-pointer.
4076
+
/// Expects a pointer. If the pointer is `NULL` [&memfree] will do nothing.
0 commit comments