0

While trying to solve the question How to print a sqlite table content with genie programming language I found out that I could try to call PrintSingleRecipe as a callback from Database.exec. However, it seems that a callback cannot be a regular function, they have some property that I do not seem to find over in the internets.

I am calling it in this way:

else if response is "3" //Show a Recipe
    res:string = UserInterface.raw_input("Select a recipe -> ")
    sql:string = "SELECT * FROM Recipes WHERE pkID = %res"
    db.exec(sql, PrintSingleRecipe, null)

And the function itself looks like:

def PrintSingleRecipe(n_columns:int, values:array of string, column_names:array of string)
    print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    for i:int = 0 to n_columns
        stdout.printf ("%s = %s\n", column_names[i], values[i])
    print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    print "Ingredient list"
    print " "
    stdout.printf("%-5s", "%03i" )

However, I get the following error at compilation:

valac --pkg sqlite3 --pkg gee-0.8 cookbook.gs
cookbook.gs:42.26-42.42: error: Argument 2: Cannot convert from `PrintSingleRecipe' to `Sqlite.Callback?'
            db.exec(sql, PrintSingleRecipe, null)
                         ^^^^^^^^^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)

How to properly run the callback in Genie?

Community
  • 1
  • 1
lf_araujo
  • 1,991
  • 2
  • 16
  • 39

1 Answers1

1

The Vala compiler does type checking on a function when a function is passed as a parameter. When a function is used in this way it is called a "delegate". Specifically the Vala compiler will check that the function's signature matches the signature of the delegate type definition. A function's signature is made up of its parameter types and return type. Cannot convert from 'PrintSingleRecipe' to 'Sqlite.Callback?' means the PrintSingleRecipe function's signature doesn't match the Sqlite.Callback delegate definition's signature.

The Sqlite.Callback delegate definition is shown here: http://valadoc.org/#!api=sqlite3/Sqlite.Callback You have rightly identified the parameters required are int, array of string, array of string, but you also need to include the return type. In this case it is an int. So your callback should look like:

def PrintSingleRecipe(n_columns:int, 
        values:array of string, 
        column_names:array of string
        ):int
    print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    for i:int = 0 to n_columns
        stdout.printf ("%s = %s\n", column_names[i], values[i])
    print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    print "Ingredient list"
    print " "
    stdout.printf("%-5s", "%03i" )
    return 0

Returning non-zero will abort the query. See https://www.sqlite.org/capi3ref.html#sqlite3_exec

AlThomas
  • 4,169
  • 12
  • 22
  • Hi AIThomas, how to call the variable res from the sql string? The syntax that I used do not work: ```res:string = UserInterface.raw_input("Select a recipe -> ") sql:string = "SELECT * FROM Recipes WHERE pkID = %res"``` – lf_araujo Dec 05 '15 at 10:48
  • You can use string concatenation: `sql:string = "SELECT * FROM Recipes WHERE pkID = " + res` or a template: `sql:string = @"SELECT * FROM Recipes WHERE pkID = $res"` – AlThomas Dec 05 '15 at 11:27