Reputation: 33607
I was looking at how Red/System hooks up with C library functions from Windows DLLs, Linux/Android .so shared libraries, and OS/X .dylib, with the #import
syntax:
#import [
"libc.so.6" cdecl [
allocate: "malloc" [
size [integer!]
return: [byte-ptr!]
]
free: "free" [
block [byte-ptr!]
]
/* ... */
]
Works for all the basic types, but what do you do when a function wants a pointer to a pointer? For instance, what if you were trying to bind to something like getline()
, which has the prototype:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
One way of calling this (the way I want to call it...) is where the incoming lineptr is not a preallocated buffer, but rather null
. In this case, getline allocates the buffer for you and modifies the char* so it is no longer null.
As a first try, I did:
getline: "getline" [
lineptr [byte-ptr!] ;-- char **
n [pointer! [integer!]] ;-- size_t *
stream [byte-ptr!] ;-- FILE *
return: [integer!] ;-- ssize_t
]
But since there isn't such a thing as a pointer! [c-string!]
or similar, I don't see how to call it. Can I get the address of a c-string!
local variable and pass it as a byte-ptr!
somehow?
Upvotes: 3
Views: 189
Reputation: 96
Red/System [
Title: "derp"
]
#import [
LIBC-file cdecl [
_fdopen: "fdopen" [
fd [integer!]
type [c-string!]
return: [pointer! [byte!]]
]
_getline: "getline" [
line [pointer! [integer!]]
n [pointer! [integer!]]
stream [pointer! [byte!]]
return: [integer!]
]
]
]
getline: func [
stream [pointer! [byte!]]
return: [c-string!]
/local
line [integer!]
n [integer!]
] [
line: 0
n: 0
_getline :line :n stream
as c-string! line
]
stream: _fdopen 0 "r"
line: getline stream
print line
This works.
Upvotes: 7
Reputation: 1679
In a world of little Red documentation, one actual Red/System Specification Document is pretty useful, and that section contains the answer indirectly in another example:
p: declare pointer! [byte!] ;-- char *p;
which would result in:
getline: "getline" [
lineptr [pointer! [byte!]] ;-- *char *
n [pointer! [integer!]] ;-- *size_t
stream [pointer! [byte!]] ;-- *char
return: [integer!] ;-- ssize_t
]
Upvotes: 2