首页 > 解决方案 > 在 Swift 中调用的 C 结构在调用本机代码时未更新

问题描述

我有一个 C 结构:

 struct FastSax { 
        int parseErrorType;
        int parserStatus;
        int cacheIndex;
        char* input;
        int (* findOpen)(FastSax *, int);
        int (* findClose)(FastSax *, int); 
        void (* print)(char *);
        char* (* parse)(FastSax* , const char*); 
    };

像这样初始化:

FastSax* getDefault() {

    FastSax *sax = malloc(sizeof (FastSax));
    sax->cacheIndex = -1;


    sax->findOpen = &findOpen;
    sax->findClose = &findClose;
    sax->parse = & parse;
    sax->hasMoreTokens = &hasMoreTokens;
    sax->fetchNextToken = &fetchNextToken;
    sax->print = &print;


    sax->parseErrorType = PARSE_ERROR_NONE;
    sax->parserStatus = PARSE_STATUS_INSUFFICIENT_DATA;

    sax->input = malloc(50 * sizeof (char));

    strncpy(sax->input, "", 10);
    sax->input[strlen(sax->input)] = '\0';


    return sax;

}

我在处理文件中的行的循环中调用 parse 函数。parse 函数运行并根据其输出更新结构对象的一些属性。

     char* parse(FastSax* fs , const char *freshData) {

       //parse operations on freshData
fs.cacheIndex = strlen(freshData);
fs.parserStatus = 4;


    /**Parser code here**/


//not a constant string
return "the-result-of-the-parse";
    }

在 Swift 中,我这样做:

class ParserClient{
    let fastSax = getDefault()


 func parse(line: String) -> Int{

        let ptr = fastSax

        var status:Int32 = -1

        let fs: FastSax = ptr!.withMemoryRebound(to: FastSax.self, capacity: 1) {
            $0.pointee
        }

        let out = fs.parse(ptr , line)


        //consume the first token
        if fs.parseErrorType == PARSE_ERROR_NONE{
            var token = String(cString: out)
            self.delegate.endEntry(entry: token)

            while true {
                var _token = String(cString: fs.parse(ptr ,""))

                Log.out("\(_token) , parser-status: \(fs.parserStatus)")

                if fs.parserStatus == PARSE_STATUS_OK {
                    self.delegate.endEntry(entry: _token)
                }else{
                    break
                }

            }

        }else{
            Log.out("Error: parser-status: \(fs.parserStatus) , error-type: \(fs.parseErrorType)")
        }

        return Int(fs.parserStatus)
    }

}

在 C 中调用解析器代码时,它可以正常工作。

但是当从 Swift 调用时,我注意到结构对象,即fs属性在 while 循环的每次迭代中都没有更新。

问题:

如何确保在调用 C 代码时更新结构的属性。

从 Swift 调用的结构的副本是否与 C 使用的不同?

标签: cswift

解决方案


从 Swift 调用的结构的副本是否与 C 使用的不同?

确切地。这个

let fs: FastSax = ptr!.withMemoryRebound(to: FastSax.self, capacity: 1) {
    $0.pointee
}

是复制 . 所指向的结构的一种(复杂)方法ptr。然后

let out = fs.parse(ptr , line)

更新指向的结构ptr(这是之前获得的默认结构)而不是指向的结构fs

你可能想要的只是

let out = fastSax!.pointee.parse(fastSax, line)

假设fastSax不是nil。如果不能保证,请使用可选绑定或可选链接。ptrfs变量不是必需的。


推荐阅读