0

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 i.e. 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?

2
  • In getDefault() shouldn't you be returning a pointer, instead of a copy of the malloced struct? Commented Nov 30, 2019 at 13:49
  • Oops, wrong copy. I had changed that before. I will update it now Commented Nov 30, 2019 at 13:51

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Wow. @Martin R, I have been using your code all over stackoverflow to get how this works. I will update and let you know how it goes now. Thanks a lot!
Tested. So precise. It works really fine. Thanks @Martin R
Also, what is an easier(less complicated , lol) way of making copy of the said struct?
Oops, I thought you were referring to a separate copy when you talked about the complicated bit. Is the complicated one the same copy or a separate copy?
@gbenroscience: It is a “separate” copy because structs are value types.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.