LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-21-2008, 01:49 PM   #1
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Question Can someone please explain why I needed to add a second definition of a callback fct?


I was writing some code for a sqlite3 application and wanted to use this code
PHP Code:
//*****************************************************
//
// Call-back function used by sqlite3_exec()
//
//*****************************************************
static int process_sql// Return 0 on success          
  
sqlite3 *db,          // Data base being processed    
  
int argc,             // Number of row values returned by query
  
char **argv,          // Data values returned                  
  
char **azColName)     // Name of the data columns returned     
{                                                                
  if (
argc 0) return 1;                                        
  if (
partition(argv[0], db)) {                                  
    
// If we get here we had a data base error. Abort.           
    
sqlite3_close(db);                                           
    exit (
1);                                                    
  }                                                              
  
// Partition the root word                                     
  
if (partition(argv[0], db)) {                                  
    
// If we get here we had a data base error. Abort.           
    
sqlite3_close(db);                                           
    exit (
1);                                                    
  }                                                              
  return 
0;                                                      

with this call
Code:
  rc = sqlite3_exec(db, select, process_sql, db, &errmsg);
and I got an error message that I had a pointer type missmatch in argument 3.

When I replaced that code with this
Code:
  int (*callback)();
  callback=process_sql;
  rc = sqlite3_exec(db, select, callback, db, &errmsg);
the application compiled and ran with no problem.

My problem is that, as far as I can see, both calls should have been identical.

Is it, perhaps, some optimization changing the "standard" function definition?

Here's the (very simple) compile line I was using:
Code:
gcc comb3.c -lsqlite3 -o comb3

Last edited by PTrenholme; 09-21-2008 at 01:50 PM.
 
Old 09-21-2008, 04:09 PM   #2
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
Your argument list doesn't agree with the argument list defined by sqlite3 (the first argument is a void *)
Code:
typedef int (*sqlite_callback)(void*,int,char**, char**);
You should be able to do a type cast
Code:
rc = sqlite3_exec(db, select, (sqlite3_callback) process_sql, db, &errmsg);

Last edited by graemef; 09-21-2008 at 04:12 PM.
 
Old 09-22-2008, 08:43 AM   #3
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Original Poster
Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Agreed, the first argument is typed as a void pointer to enable one to pass a pointer to anything into the call back function. But the "type mismatch" compile error specifically referred to the third argument.

Note that the compiler did not complain about
Code:
  int (*callback)();
  callback=process_sql;
  rc = sqlite3_exec(db, select, callback, db, &errmsg);
which, I believe, shows that the "type" of process_sql is int *(void*,int,char**,char**), and my C language specification reference book (C a Reference Manual, Harbison and Steele, 1984) agrees.

Note also that the specification of the sqlite3_exec function:
Code:
int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);
makes no mention of a sqlite3_callback type. Further, the definition of the sqlite3_callback
Code:
typedef int (*sqlite3_callback)(void*,int,char**, char**);
looks to me a match with
Code:
static int process_sql( // Return 0 on success          
  sqlite3 *db,          // Data base being processed    
  int argc,             // Number of row values returned by query
  char **argv,          // Data values returned                  
  char **azColName)     // Name of the data columns returned
except for the static qualification. (Which is there because I was looking at the code in the SQLite in 5 Minutes or Less on the SQLite web site, vis:
Code:
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
). I don't think that the static should cause the compiler to complain. Anyhow, I removed the static and still get:
Code:
comb4.c: In function ‘main’:
comb4.c:269: warning: passing argument 3 of ‘sqlite3_exec’ from incompatible pointer type
when I compile.

So I'm still puzzled.
 
Old 09-22-2008, 12:50 PM   #4
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

The problem (as you verified) is very definitely not the "static". It's just weirdness with C/C++ function pointer syntax.

Here's a link that might help:

http://publications.gbdirect.co.uk/c..._pointers.html
 
Old 09-22-2008, 03:55 PM   #5
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Original Poster
Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Hum. O.K., I think I've got it after looking at paulsm's reference. (Thanks Paul.)

The function declaration int foo() {...} tells the compiler to generate code to invoke foo when it sees a foo() somewhere in the code. But a pointer to foo has to be declared as int (*foo)() and so my use of an unqualified foo in the sqlite3_callback function was not correct.

The construct suggested by gramef works because it instructs the compile to use a pointer to the function.

Unfortunately that "explanation" seems to accurately convey my still confused state. Can anyone do it any more clearly?
 
Old 09-22-2008, 05:20 PM   #6
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, PTrenholme -

You're exactly right.

The syntax *is* confusing - but this statement is absolutely correct:
Quote:
The function declaration int foo() {...} tells the compiler to generate code to invoke foo when it sees a foo() somewhere in the code. But a pointer to foo has to be declared as int (*foo)() and so my use of an unqualified foo in the sqlite3_callback function was not correct.
*Why* is the syntax so weird? Don't know. I imagine it basically has to do with the parenthesis operators (which are overloaded for "grouping" and "function call"), the "*" operator (which is overloaded for "multiplication", "pointer dereferencing" and "pointer declaration") and the relative precedence between these operators. But the basic answer is "it's just weird".

'Hope that helps .. PSM
 
Old 09-22-2008, 05:36 PM   #7
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
I notice that you are getting a warning not an error.
What happens if you declare process_sql to exactly match with sqlite3_callback (ie with void*) and then typecast within the function to a sqlite*?
 
Old 09-23-2008, 12:07 PM   #8
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Original Poster
Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
graemef, since the warning was generated by the calling program, not the called one, I tried
Code:
  rc = sqlite3_exec(db, select, (void *) process_sql, db, &errmsg);
which worked like a charm.

Of course your original suggestion:
Code:
rc = sqlite3_exec(db, select, (sqlite3_callback) process_sql, db, &errmsg);
is a better solution since it make the code much more legible.

But, at the point in the compilation where the warning is being generated the types of the arguments of the callback function are irrelevant since all that's being passes is a pointer to a function. Thus changing the type of the "pointer passed as the first argument to the callback function" in the callback function declaration has no effect on the warning message.

By the way, if you're interested in the complete program it's posted here. It's a app to take a string of characters from the standard input and write all possible permutations of all substrings of the input characters (of two characters or more), to the standard output. The OP in that thread was trying to debug an app that was intended to find all words that could be generated by rearranging the letters in an input word using a home-grown linked list program. I was trying to show the OP that reinventing the wheel was not always the best way to go. . .
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
No LILO fct. after motherboard upgrade jbuckley2004 Mandriva 2 01-05-2007 09:58 AM
A problem about callback scanner Programming 6 07-05-2006 03:40 AM
Help needed to add/remove devices without rebooting. szehanz Linux - Newbie 2 03-18-2005 06:27 AM
Help! explain needed for the output of iptables -L mrpc_cambodia Red Hat 2 07-20-2004 11:16 PM
Problem with Callback! Linuxnewbie Linux - Networking 1 02-24-2004 01:55 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:04 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration