How to assign a reference of a function

I have 2 functions


func VolExtContextInitializer( extData: UnsafeMutablePointer<Void>, ctxType:UnsafePointer<UInt8>, ctx:FREContext, inout numFunctionsToTest:UnsafeMutablePointer<UInt32>, functionsToSet:AutoreleasingUnsafeMutablePointer<FRENamedFunction>){ 
     var numOfFunc:UInt32 = 2
          //stuff
}


func VolumeExtensionInitializer(inout extDataToSet: AutoreleasingUnsafeMutablePointer<Void>, inout ctxInitializerToSet: UnsafeMutablePointer<FREContextInitializer> , inout ctxFinalizerToSet: UnsafeMutablePointer<FREContextFinalizer>){
     extDataToSet = nil
     ctxInitializerToSet = &VolExtContextInitializer
}


I need to set ctxInitializerToSet to the reference of VolExtContextInitializer as dictated by the C library attached to this. This (ctxInitializerToSet = &VolExtContextInitializer) gives me the error of "Types of expression is ambiguous without more context". I'm not sure how to make it more clear for the compiler.


thanks.

Answered by OOPer in 44349022

OK, if the two function types are defined as such in C, the two functions in Swift needs to have the following header.

To match FREContextInitializer:

func VolExtContextInitializer(extData: UnsafeMutablePointer<Void>,
    ctxType: UnsafePointer<UInt8>,
    ctx: FREContext,
    numFunctionsToTest: UnsafeMutablePointer<UInt32>,
    functionsToSet: UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)


For FREInitializer:

func VolumeExtensionInitializer(extDataToSet: UnsafeMutablePointer<UnsafeMutablePointer<Void>>,
    ctxInitializerToSet: UnsafeMutablePointer<FREContextInitializer?>,
    ctxFinalizerToSet: UnsafeMutablePointer<FREContextFinalizer?>)


So, your VolumeExtensionInitializer should be like this:

func VolumeExtensionInitializer(extDataToSet: UnsafeMutablePointer<UnsafeMutablePointer<Void>>,
    ctxInitializerToSet: UnsafeMutablePointer<FREContextInitializer?>,
    ctxFinalizerToSet: UnsafeMutablePointer<FREContextFinalizer?>)
{
    extDataToSet.memory = nil
    ctxInitializerToSet.memory = VolExtContextInitializer
    //...
}

The codes you have shown is sort of broken and it's hard for me to believe those to work. Can you show me the original C declarations of the function headers and the function types?

/*
* Defines the signature for the initializer that is called each time
* a new AS ExtensionContext object is created.
*
* @param extData The extension client data provided to the FREInitializer function as extDataToSet.
*
* @param ctxType Pointer to the contextType string (UTF8) as provided to the AS createExtensionContext call.
*
* @param ctx The FREContext being initialized.
*
* @param numFunctionsToSet The number of elements in the functionsToSet array.
*
* @param functionsToSet A pointer to an array of FRENamedFunction elements.
*/
typedef void (*FREContextInitializer)(
        void*                    extData          ,
        const uint8_t*           ctxType          ,
        FREContext               ctx              ,
        uint32_t*                numFunctionsToSet,
        const FRENamedFunction** functionsToSet
);

/*
* The initialization function provided by each extension must conform
* to the following signature.
*
* @param extDataToSet Provided for the extension to store per-extension instance data.
*            For example, if the extension creates
*            globals per-instance, it can store a pointer to them here.
*
* @param ctxInitializerToSet Must be set to a pointer to a function
*            of type FREContextInitializer. Will be invoked whenever
*            the ActionScript code creates a new context for this extension.
*
* @param ctxFinalizerToSet Must be set to a pointer to a function
*            of type FREContextFinalizer.
*/
typedef void (*FREInitializer)(
        void**                 extDataToSet       ,
        FREContextInitializer* ctxInitializerToSet,
        FREContextFinalizer*   ctxFinalizerToSet
);


Here's part of the C file.

It's an API so the function names are a bit different.

VolExtContextInitializer belongs to FREContextInitializer

and VolumeExtensionInitializer to FREInitializer. Noctice the comment

/* @param ctxFinalizerToSet Must be set to a pointer to a function
*            of type FREContextFinalizer.
*/

by the way, this is the Objective-C equivalent. If anybody can tranlate this, it'll be great!


void VolExtContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet){
     *numFunctionsToTest = 0;
     FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest;
     *functionsToSet = func;
}

void VolumeExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet){
     *extDataToSet = NULL;
     *ctxInitializerToSet = &VolExtContextInitializer;
}
Accepted Answer

OK, if the two function types are defined as such in C, the two functions in Swift needs to have the following header.

To match FREContextInitializer:

func VolExtContextInitializer(extData: UnsafeMutablePointer<Void>,
    ctxType: UnsafePointer<UInt8>,
    ctx: FREContext,
    numFunctionsToTest: UnsafeMutablePointer<UInt32>,
    functionsToSet: UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)


For FREInitializer:

func VolumeExtensionInitializer(extDataToSet: UnsafeMutablePointer<UnsafeMutablePointer<Void>>,
    ctxInitializerToSet: UnsafeMutablePointer<FREContextInitializer?>,
    ctxFinalizerToSet: UnsafeMutablePointer<FREContextFinalizer?>)


So, your VolumeExtensionInitializer should be like this:

func VolumeExtensionInitializer(extDataToSet: UnsafeMutablePointer<UnsafeMutablePointer<Void>>,
    ctxInitializerToSet: UnsafeMutablePointer<FREContextInitializer?>,
    ctxFinalizerToSet: UnsafeMutablePointer<FREContextFinalizer?>)
{
    extDataToSet.memory = nil
    ctxInitializerToSet.memory = VolExtContextInitializer
    //...
}
func VolExtContextInitializer(extData: UnsafeMutablePointer<Void>,
    ctxType: UnsafePointer<UInt8>,
    ctx: FREContext,
    numFunctionsToTest: UnsafeMutablePointer<UInt32>,
    functionsToSet: UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)
{
    //???
    let funcs: UnsafePointer<FRENamedFunction> = UnsafePointer(malloc(strideof(FRENamedFunction) * Int(numFunctionsToTest.memory)))
    //???
}

I leave some parts for you. As `func` is a reserved word in Swift, you need to rename it (or enclose with ``).

Thanks a bunch but I'm getting this error


Cannot assign a value of type '(UnsafeMutablePointer<Void>, UnsafePointer<UInt8>, FREContext, UnsafeMutablePointer<UInt32>, UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>) -> ()' to a value of type 'FREContextInitializer?'


for


ctxInitializerToSet.memory = VolExtContextInitializer

The word memory is not hilighted when I assign VolExtContextInitializer

Are you using Xcode 6.x? I can see the message you have shown only in Xcode 6.4.

In that case, no way. You cannot provide C-function pointers from Swift 1.x. Use Swift 2 with Xcode 7. Or, you need to live with Objective-C codes mixed.

If you got that message with Swift 2, you need to provide more info.

yeah, I'm running xcode 6.4 with swift 1.2.

Thanks.

Xcode 7 is expected to get GM release in a month, I recommend you start migrating your project to Swift 2 soon. Many developers watching the dev forums will help you.

Hi,

I'm trying to assign properties to the objects<FRENamedFunction> but I'm getting "Cannot assign to property: subscript is get-only"


func DatePickerContextInitializer(  extData: UnsafeMutablePointer<Void>,
    ctxType:UnsafePointer<UInt8>,
    ctx:FREContext,
    numFunctionsToTest:UnsafeMutablePointer<UInt32>,
    functionsToSet:UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)
{
  
  
    numFunctionsToTest.memory = 2
    let functions: UnsafePointer<FRENamedFunction> = UnsafePointer(malloc(strideof(FRENamedFunction) * Int(numFunctionsToTest.memory)))

    functions[0].name = UnsafePointer<UInt8>("show")// error here!

    functionsToSet.memory = functions
  
}


Maybe I need another way to create the Object<FRENamedFuntion> ?

Oh, the C type definition is this


typedef struct FRENamedFunction_ {
     const uint8_t* name;
     void*          functionData;
     FREFunction    function;
} FRENamedFunction;

The line you designated has two errors. One is represented by the error message.

"Cannot assign to property: subscript is get-only"

In this case, this message shows that you cannot modify the content pointed by UnsafePointer, which is similar to const FRENamedFunction* in C.

So, changed the type of `functions` to UnsafeMutablePointer, with which you can modify the content using subscript or .member.

    let functions: UnsafeMutablePointer<FRENamedFunction> = UnsafeMutablePointer(malloc(strideof(FRENamedFunction) * Int(numFunctionsToTest.memory)))

This change forces you to convert the types in the assignment of the last line.

    functionsToSet.memory = UnsafePointer(functions)


Another error remains. You cannot convert String literals to pointers in the form you have shown.

I'm not sure if it is the best way to do this sort of things, but I would write something like this:

    functions[0].name = ("show\0" as StaticString).utf8Start

(As StaticString's property utf8Start is not guaranteed to have a NUL-terminated byte sequence, I added the terminating null character manually.)

Thanks that works but now I'm getting an error on this


func DatePickerContextInitializer(  extData: UnsafeMutablePointer<Void>,
    ctxType:UnsafePointer<UInt8>,
    ctx:FREContext,
    numFunctionsToTest:UnsafeMutablePointer<UInt32>,
    functionsToSet:UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)
{
    numFunctionsToTest.memory = 2
    let functions: UnsafeMutablePointer<FRENamedFunction> = UnsafeMutablePointer(malloc(strideof(FRENamedFunction) * Int(numFunctionsToTest.memory)))
    functions[0].name = ("show\0" as StaticString).utf8Start

    functionsToSet.memory = functions // error - Cannot assign a value of type 'UnsafeMutablePointer<FRENamedFunction>' to a value of type 'UnsafePointer<FRENamedFunction>'

}


I tried changing

functionsToSet:UnsafeMutablePointer<UnsafePointer<FRENamedFunction>>)


to


functionsToSet:UnsafePointer<UnsafeMutablePointer<FRENamedFunction>>)


but Xcode's editor physically doesn't like it by erroring out and restarting and the compiler throws a Signal: Abort trap: 6 error

Three things:


- Read carefully

- Do not try changing the method signature derived from C-API requirements.

- Send a Bug Report for Abort trap: 6, this is what should not happen

How to assign a reference of a function
 
 
Q