Как создать привязку Red/System к функции, которая принимает указатель на указатель?
Я смотрел на то, как Red/System соединяется с функциями библиотеки C из библиотек DLL Windows, общих библиотек Linux/Android .so и OS/X .dylib с #import
синтаксис:
#import [
"libc.so.6" cdecl [
allocate: "malloc" [
size [integer!]
return: [byte-ptr!]
]
free: "free" [
block [byte-ptr!]
]
/* ... */
]
Работает для всех основных типов, но что вы делаете, когда функция хочет указатель на указатель? Например, что если вы пытаетесь связать что-то вроде getline()
, который имеет прототип:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
Один из способов вызвать это (как я хочу назвать это...) - это когда входящий lineptr не является заранее выделенным буфером, а скорее null
, В этом случае getline выделяет для вас буфер и изменяет char*, чтобы он больше не был нулевым.
В качестве первой попытки я сделал:
getline: "getline" [
lineptr [byte-ptr!] ;-- char **
n [pointer! [integer!]] ;-- size_t *
stream [byte-ptr!] ;-- FILE *
return: [integer!] ;-- ssize_t
]
Но так как нет такой вещи как pointer! [c-string!]
или подобное, я не вижу, как это назвать. Могу ли я получить адрес c-string!
локальная переменная и передать его как byte-ptr!
каким-то образом?
2 ответа
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
Это работает.
В мире маленькой документации Red один документ Red/System Specification довольно полезен, и этот раздел косвенно содержит ответ в другом примере:
p: declare pointer! [byte!] ;-- char *p;
что приведет к:
getline: "getline" [
lineptr [pointer! [byte!]] ;-- *char *
n [pointer! [integer!]] ;-- *size_t
stream [pointer! [byte!]] ;-- *char
return: [integer!] ;-- ssize_t
]