Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

importing C libraries #235

Open
rutlang opened this issue Aug 28, 2021 · 9 comments
Open

importing C libraries #235

rutlang opened this issue Aug 28, 2021 · 9 comments

Comments

@rutlang
Copy link

rutlang commented Aug 28, 2021

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

@arshajii
Copy link
Member

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.

@rutlang
Copy link
Author

rutlang commented Aug 30, 2021

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?

@markhend
Copy link
Collaborator

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

@arshajii
Copy link
Member

arshajii commented Aug 30, 2021

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.

@markhend
Copy link
Collaborator

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)))

@arshajii
Copy link
Member

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.

@rutlang
Copy link
Author

rutlang commented Sep 8, 2021

Thanks @arshajii. How to import from_ptr()?

@markhend
Copy link
Collaborator

markhend commented Sep 8, 2021

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

@arshajii
Copy link
Member

arshajii commented Sep 8, 2021

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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants