【问题标题】:How to create a Red/System binding to a function that takes a pointer to a pointer?如何创建一个红色/系统绑定到一个函数,该函数需要一个指向指针的指针?
【发布时间】:2014-01-02 23:06:07
【问题描述】:

我正在研究 Red/System 如何使用 #import 语法与来自 Windows DLL、Linux/Android .so 共享库和 OS/X .dylib 的 C 库函数挂钩:

#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*,使其不再为 null。

作为第一次尝试,我做到了:

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! 以某种方式传递吗?

【问题讨论】:

    标签: pointers shared-libraries getline red red-system


    【解决方案1】:
    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
    

    这行得通。

    【讨论】:

    • 谢谢!这可行,尽管 LIBC 的 getline 的返回是检索到的行的长度(不是字符串),所以它将是一个整数......你可以编辑你的答案(我也可以)。但我会让你去做。 :-)
    【解决方案2】:

    在一个只有少量 Red 文档的世界中,一个实际的 Red/System Specification Document 非常有用,该部分在另一个示例中间接包含了答案:

    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
    ]
    

    【讨论】:

    • 很高兴提及链接。我想我在这里没有真正理解的主要事情是 Red/System 的 GET-WORD 应用程序!意思是“地址”。
    猜你喜欢
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 2021-10-28
    • 2016-02-23
    相关资源
    最近更新 更多