简体   繁体   English

在 Swift 中调用的 C 结构在调用本机代码时不会更新

[英]C struct called in Swift not being updated when it calls native code

I have a C Struct:我有一个 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*); 
    };

Initialized like this:初始化如下:

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;

}

I am calling the parse function in a loop that processes lines from a file.我在处理文件行的循环中调用 parse 函数。 The parse function runs and based on its output, updates some properties of the struct object.解析函数运行并根据其输出更新结构对象的一些属性。

     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";
    }

In Swift, I do:在 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)
    }

}

When the parser code is invoked in C, it works fine.当在 C 中调用解析器代码时,它工作正常。

But when called from Swift, I noticed that the struct object ie fs properties were not being updated on each iteration of the while loop.但是当从 Swift 调用时,我注意到在 while 循环的每次迭代中都没有更新结构对象,即fs属性。

Question:题:

How do I make sure that the struct's properties are updated when it calls C code.我如何确保在调用 C 代码时更新结构的属性。

Is the copy of the struct invoked from Swift different from the one being used by C?从 Swift 调用的结构副本与 C 使用的不同吗?

Is the copy of the struct invoked from Swift different from the one being used by C?从 Swift 调用的结构副本与 C 使用的不同吗?

Exactly.确切地。 This这个

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

is a (complicated) way of making a copy of the struct pointed to by ptr .是制作ptr指向的结构副本的(复杂)方法。 Then然后

let out = fs.parse(ptr , line)

updates the structure pointed to by ptr (which is the default structure obtained before) and not the structure pointed to by fs .更新ptr指向的结构(这是之前获得的默认结构)而不是fs指向的结构。

What you probably want is simply你可能想要的只是

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

assuming that fastSax is not nil .假设fastSax不是nil Use optional binding or optional chaining if that is not guaranteed.如果不能保证,请使用可选绑定或可选链接。 The ptr and fs variables are not needed.不需要ptrfs变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM