简体   繁体   中英

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

I have a C Struct:

 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. 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:

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.

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.

Question:

How do I make sure that the struct's properties are updated when it calls C code.

Is the copy of the struct invoked from Swift different from the one being used by C?

Is the copy of the struct invoked from Swift different from the one being used by 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 . 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 .

What you probably want is simply

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

assuming that fastSax is not nil . Use optional binding or optional chaining if that is not guaranteed. The ptr and fs variables are not needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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