Как создать привязку 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
]
Другие вопросы по тегам