seq icon indicating copy to clipboard operation
seq copied to clipboard

importing C libraries

Open rutlang opened this issue 4 years ago • 9 comments

How are functions from third-party or user C libraries imported when the arguments include structs or enums?

rutlang avatar Aug 28 '21 17:08 rutlang

Hi @rutlang, basically the following:

  • For structs, you can use the corresponding tuple. For example, struct { double a; long b; bool c } corresponds to Tuple[float, int, bool]. You can use i32 for 32-bit int etc. (int and float in Seq are actually 64-bit). There is also Ptr[T] for a T* in C.
  • For enums, you can just pass an i32 containing the enum value. For example, if you have enum { A = 0; B = 1; C = 2; } and wanted to pass B, you would use i32(1) in Seq.

arshajii avatar Aug 29 '21 05:08 arshajii

Thanks @arshajii. Follow up question: if the imported C functions require pointer arguments, how does one provide the addresses of Seq variables (different types, including strings, tuples (for structs), lists (for arrays?), and perhaps even ints) in the function call?

rutlang avatar Aug 30 '21 07:08 rutlang

Hi @rutlang. For strings, the tutorial has an example .

markhend avatar Aug 30 '21 14:08 markhend

You can use __ptr__(x) to get a pointer to variable x, similar to &x in C.

So e.g.

# double foo(struct { bool, int64 } *x)
from C import foo(Ptr[Tuple[bool, int]]) -> float
x = (True, 42)
y = foo(__ptr__(x))

For strings, you can use .c_str() to get a char* you can pass to C functions. If you want to get the underlying pointer from a list you can also use .arr.ptr. Let me know if this all makes sense, or there are any other cases you were wondering about.

arshajii avatar Aug 30 '21 14:08 arshajii

Is this the recommended way to handle the case where the variable is an int in C and i32 in Seq?

# int sum_of_elements(int *arr , int n)
from C import LIBRARY.sum_of_elements(Ptr[i32], i32) -> i32
L = [i32(n) for n in range(1, 5)]
print sum_of_elements(L.arr.ptr, i32(len(L)))

markhend avatar Aug 30 '21 15:08 markhend

Is this the recommended way to handle the case where the variable is an int in C and i32 in Seq?

# int sum_of_elements(int *arr , int n)
from C import LIBRARY.sum_of_elements(Ptr[i32], i32) -> i32
L = [i32(n) for n in range(1, 5)]
print sum_of_elements(L.arr.ptr, i32(len(L)))

Yes that's right. You can also create the pointer directly:

p = Ptr[i32](5)  # similar to malloc(5 * sizeof(int)) in C
p[0] = ...
p[1] = ... # etc.

arshajii avatar Aug 30 '21 15:08 arshajii

Thanks @arshajii. How to import from_ptr()?

rutlang avatar Sep 08 '21 16:09 rutlang

Hi @rutlang. Where is the from_ptr() function? Does this FFI info help?

markhend avatar Sep 08 '21 19:09 markhend

There is an str.from_ptr() which converts a C-string back to str, e.g. str.from_ptr('abc'.c_str()). This should be usable directly without imports -- were you asking about this?

arshajii avatar Sep 08 '21 19:09 arshajii