3

我正在研究 Red/System 如何与来自 Windows DLL、Linux/Android .so 共享库和 OS/X .dylib 的 C 库函数挂钩,#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
]

但由于没有 apointer! [c-string!]或类似的东西,我不知道如何称呼它。我可以获取c-string!局部变量的地址并将其作为byte-ptr!某种方式传递吗?

4

2 回答 2

7
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

这行得通。

于 2013-12-15T16:29:18.157 回答
2

在红色文档很少的世界中,一个实际的红色/系统规范文档非常有用,该部分在另一个示例中间接包含了答案:

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
]
于 2013-12-16T02:49:06.143 回答