Shiplu Mokaddim
Shiplu Mokaddim

Reputation: 57640

"Undefined reference to" error even function is declared and defined

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

Answers (5)

Jari
Jari

Reputation: 2152

In case you plan to use functions in different compilation units, you should not declare them static.

Upvotes: 0

mathematician1975
mathematician1975

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

Adam Rosenfield
Adam Rosenfield

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

YePhIcK
YePhIcK

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

Alex
Alex

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

Related Questions