Reputation: 57640
I have these 2 c file and a header file. All these files are built by a Makefile
.
mysql_storage.h
#include <stdio.h>
#include <mysql.h>
#include <glib/gstdio.h>
#if 1
typedef enum {
STORAGE_OK = 0,
STORAGE_NO_SUCH_USER,
STORAGE_INVALID_PASSWORD,
STORAGE_ALREADY_EXISTS,
STORAGE_OTHER_ERROR/* Error that isn't caused by user input, such as
a database that is unreachable. log() will be
used for the exact error message */
} storage_status_t;
typedef enum
{
MYSQL_PASS_CHECK_ONLY = -1,
MYSQL_PASS_UNKNOWN = 0,
MYSQL_PASS_WRONG,
MYSQL_PASS_OK
} mysql_pass_st;
#endif
static void mysql_storage_init( void );
static void mysql_storage_deinit( void );
static storage_status_t mysql_storage_load(const char *password );
static storage_status_t mysql_storage_check_pass( const char *nick, const char *password );
static storage_status_t mysql_storage_save( int overwrite );
static storage_status_t mysql_storage_remove( const char *nick, const char *password );
mysql_storage.c
#include "mysql_storage.h"
MYSQL *mysql;
static void mysql_storage_init( void ) {
if (mysql_init(mysql) == NULL)
fprintf( stderr, "Can not initialize MySQL. Configuration won't be saved.");
if (!mysql_real_connect(mysql, "localhost", "USERNAME", "PASSWORD", NULL, 3306, NULL, 0))
fprintf( stderr, "%s\nConfiguration won't be saved.", mysql_error(mysql));
if (mysql_select_db(mysql, "DATABASENAME"))
fprintf( stderr, "%s\nConfiguration won't be saved.", mysql_error(mysql));
}
static void mysql_storage_deinit( void ) {
if(mysql!=NULL)
mysql_close(mysql);
}
static storage_status_t mysql_storage_check_pass( const char *nick, const char *password ){ return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_load(const char *password ){ return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_save( int overwrite ){ return STORAGE_OTHER_ERROR;}
static storage_status_t mysql_storage_remove( const char *nick, const char *password ){ return STORAGE_OTHER_ERROR;}
main.c
#include<stdio.h>
#include "mysql_storage.h"
int main(){
// connect mysql
mysql_storage_init();
// check a password
printf("check password: %d\n:", mysql_storage_check_pass("hello", "world"));
// close mysql
mysql_storage_deinit();
}
Lastly the Makefile
CFLAGS=-I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -g -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I.
LIBS=-L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -lglib-2.0 -L.
CC=gcc
all: main
clean:
rm main *.o
main: mysql_storage.o main.o
$(CC) main.o mysql_storage.o $(LIBS) -o main
.c.o:
$(CC) -c $(CFLAGS) $<
When I make, I get this error.
gcc main.o mysql_storage.o -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -ldl -lglib-2.0 -L. -o main
main.o: In function `main':
/home/shiplu/projects/mysql_interface/main.c:8: undefined reference to `mysql_storage_init'
/home/shiplu/projects/mysql_interface/main.c:11: undefined reference to `mysql_storage_check_pass'
/home/shiplu/projects/mysql_interface/main.c:15: undefined reference to `mysql_storage_deinit'
collect2: ld returned 1 exit status
As you can see I am linking main.o
and mysql_storage.o
. So it should not throw undefined reference error. What is the problem here?
Upvotes: 0
Views: 3797
Reputation: 2152
In case you plan to use functions in different compilation units, you should not declare them static.
Upvotes: 0
Reputation: 21351
Using the keyword static before your functions ensures that they are only visible within the compilation unit that they are defined. If you remove the static keyword from your functions you should have no problem.
Upvotes: 1
Reputation: 400146
You declared your functions mysql_storage_init
as static
, meaning they have internal linkage -- this means they are not visible to other translation units.
Since you need to call them from other object files, you should instead declare them to have external linkage by omitting the static
keyword in their declarations and definitions. The prototypes in the header file may optionally declare them extern
, but that is not required, since the linkage is external by default.
Upvotes: 4
Reputation: 5856
The static
keyword for a function means this function will have the scope of this .obj file only, which is probably not what you expect. Remove the static
keyword for function definitions and declarations (both .h and .cpp files)
Upvotes: 3
Reputation: 1684
You mysql_storage.c functions are defined as static
, which means they are not visible outside of the file. Remove static
and it should work.
Upvotes: 3