• C Mysql API连接Mysql


    最近都在查看MYsql C API文档,也遇到了很多问题,下面来简单的做一个总结。

    mysql多线程问题

    单线程

    • 一般情况下,单线程连接mysql代码如下:
     1 /*
     2         single_thread_mysql_client.cpp
     3     */
     4     #include <stdio.h>
     5     #include <string.h>
     6     #include <stdlib.h>
     7     #include <mysql/mysql.h>
     8     #include <pthread.h>
     9     #include <unistd.h>
    10 
    11     #define DBHOST      "localhost"
    12     #define DBUSER      "pca"
    13     #define DBPASS      "pca"
    14     #define DBPORT      3306
    15     #define DBNAME      "dxponline"
    16     #define DBSOCK      NULL //"/var/lib/mysql/mysql.sock"
    17     #define DBPCNT      0
    18 
    19     int main()
    20     {
    21         MYSQL_RES *result;
    22         MYSQL_ROW row;
    23         MYSQL_FIELD *field;
    24         unsigned int num_fields;
    25         unsigned int i;
    26         const char *pStatement = "SHOW TABLES";
    27         mysql_library_init(0, NULL, NULL);
    28         MYSQL *mysql = mysql_init(NULL);
    29         unsigned int timeout = 3000;
    30         mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
    31 
    32         if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
    33         {
    34             printf("connect failed: %s
    ", mysql_error(mysql));
    35             mysql_close(mysql);
    36             mysql_library_end();
    37             return 0;
    38         }
    39 
    40         printf("connect succssfully
    ");
    41 
    42         if (0 != mysql_real_query(mysql, pStatement, strlen(pStatement)))
    43         {
    44             printf("query failed: %s
    ", mysql_error(mysql));
    45             mysql_close(mysql);
    46             mysql_library_end();
    47             return 0;
    48         }
    49 
    50         result = mysql_store_result(mysql);
    51 
    52         if (result == NULL)
    53         {
    54             printf("fetch result failed: %s
    ", mysql_error(mysql));
    55             mysql_close(mysql);
    56             mysql_library_end();
    57             return 0;
    58         }
    59 
    60         num_fields = mysql_num_fields(result);
    61         printf("numbers of result: %d
    ", num_fields);
    62 
    63         while (NULL != (field = mysql_fetch_field(result)))
    64         {
    65             printf("field name: %s
    ", field->name);
    66         }
    67 
    68         while (NULL != (row = mysql_fetch_row(result)))
    69         {
    70             unsigned long *lengths;
    71             lengths = mysql_fetch_lengths(result);
    72 
    73             for (i = 0; i < num_fields; i++)
    74             {
    75                 printf("{%.*s} ", (int) lengths[i], row[i] ? row[i] : "NULL");
    76             }
    77 
    78             printf("
    ");
    79         }
    80 
    81         mysql_free_result(result);
    82         mysql_close(mysql);
    83         mysql_library_end();
    84         return 0;
    85     }
    • 执行

      make single_thread_mysql_client LDFLAGS="-g -O2 -L/usr/lib64/mysql -lmysqlclient -lpthread -lz -lm -lssl -lcrypto -ldl"

      即可获得对应单线程二进制。

    多线程

    • 多线程主要需要注意以下几点
      • mysql_library_init 和 mysql_library_end 需要放入主线程;
      • 连接句柄需要多个才能加快并发,而连接句柄由 mysql_init 生成,而 mysql_init跟随机函数 rand 有点相似,第一次需要初始化后才能线程安全,所以需要使用mysql_thread_init 和 mysql_thread_end 两个函数来保证线程安全;
    • 一般多线程连接mysql代码如下
      1 /*
      2         muti_thread_mysql_client.cpp
      3     */
      4     #include <stdio.h>
      5     #include <string.h>
      6     #include <stdlib.h>
      7     #include <mysql/mysql.h>
      8     #include <pthread.h>
      9     #include <unistd.h>
     10 
     11     #define THREAD_NUM  4
     12     #define DBHOST      "localhost"
     13     #define DBUSER      "pca"
     14     #define DBPASS      "pca"
     15     #define DBPORT      3306
     16     #define DBNAME      "dxponline"
     17     #define DBSOCK      NULL //"/var/lib/mysql/mysql.sock"
     18     #define DBPCNT      0
     19 
     20     typedef struct ThreadArgsST
     21     {
     22         int id;
     23         pthread_t *thread_id;
     24     } ThreadArgs;
     25 
     26     void *func(void *arg)
     27     {
     28         ThreadArgs *args = (ThreadArgs *)arg;
     29         MYSQL_RES *result;
     30         MYSQL_ROW row;
     31         MYSQL_FIELD *field;
     32         unsigned int num_fields;
     33         unsigned int i;
     34         unsigned int timeout = 3000;
     35         const char *pStatement = "SHOW TABLES";
     36         mysql_thread_init();
     37         MYSQL *mysql = mysql_init(NULL);
     38 
     39         if (mysql == NULL)
     40         {
     41             printf("[%ld][%d]mysql init failed: %s
    ", *args->thread_id, args->id, mysql_error(mysql));
     42             return (void *)0;
     43         }
     44 
     45         mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
     46 
     47         if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
     48         {
     49             printf("[%ld][%d]connect failed: %s
    ", *args->thread_id, args->id, mysql_error(mysql));
     50             mysql_close(mysql);
     51             mysql_thread_end();
     52             return (void *)0;
     53         }
     54 
     55         printf("[%ld][%d]connect succssfully
    ", *args->thread_id, args->id);
     56 
     57         if (0 != mysql_real_query(mysql, pStatement, strlen(pStatement)))
     58         {
     59             printf("[%ld][%d]query failed: %s
    ", *args->thread_id, args->id, mysql_error(mysql));
     60             mysql_close(mysql);
     61             mysql_thread_end();
     62             return (void *)0;
     63         }
     64 
     65         result = mysql_store_result(mysql);
     66 
     67         if (result == NULL)
     68         {
     69             printf("[%ld][%d]fetch result failed: %s
    ", *args->thread_id, args->id, mysql_error(mysql));
     70             mysql_close(mysql);
     71             mysql_thread_end();
     72             return (void *)0;
     73         }
     74 
     75         num_fields = mysql_num_fields(result);
     76         printf("[%ld][%d]numbers of result: %d
    ", *args->thread_id, args->id, num_fields);
     77 
     78         while (NULL != (field = mysql_fetch_field(result)))
     79         {
     80             printf("[%ld][%d]field name: %s
    ", *args->thread_id, args->id, field->name);
     81         }
     82 
     83         while (NULL != (row = mysql_fetch_row(result)))
     84         {
     85             unsigned long *lengths;
     86             lengths = mysql_fetch_lengths(result);
     87 
     88             for (i = 0; i < num_fields; i++)
     89             {
     90                 printf("[%ld][%d]{%.*s} ", *args->thread_id, args->id, (int) lengths[i], row[i] ? row[i] : "NULL");
     91             }
     92 
     93             printf("
    ");
     94         }
     95 
     96         mysql_free_result(result);
     97         mysql_close(mysql);
     98         mysql_thread_end();
     99         return (void *)0;
    100     }
    101 
    102     int main(int argc, char *argv[])
    103     {
    104         int thread_num;
    105 
    106         if (argc == 2)
    107         {
    108             thread_num = atoi(argv[1]);
    109         }
    110         else
    111         {
    112             thread_num = THREAD_NUM;
    113         }
    114 
    115         mysql_library_init(0, NULL, NULL);
    116         printf("argc: %d and thread_num: %d
    ", argc, thread_num);
    117 
    118         do
    119         {
    120             pthread_t *pTh = new pthread_t[thread_num];
    121             ThreadArgs *pArgs = new ThreadArgs[thread_num];
    122             int i;
    123 
    124             for (i = 0; i < thread_num; i ++)
    125             {
    126                 pArgs[i].id = i;
    127                 pArgs[i].thread_id = &pTh[i];
    128 
    129                 if (0 != pthread_create(&pTh[i], NULL, func, &pArgs[i]))
    130                 {
    131                     printf("pthread_create failed
    ");
    132                     continue;
    133                 }
    134             }
    135 
    136             for (i = 0; i < thread_num; i ++)
    137             {
    138                 pthread_join(pTh[i], NULL);
    139             }
    140 
    141             delete[] pTh;
    142             delete[] pArgs;
    143         }
    144         while (0);
    145 
    146         mysql_library_end();
    147         return 0;
    148     }
    • 执行

      make muti_thread_mysql_client LDFLAGS="-g -O2 -L/usr/lib64/mysql -lmysqlclient -lpthread -lz -lm -lssl -lcrypto -ldl"

      即可获得对应单线程二进制。

    • 连接数与连接句柄是一一对应关系,故一般使用长连接,所以需要连接池,所以上面的代码可以有优化的空间,代码见:

      1 /*
      2         muti_thread_mysql_client_pool.cpp
      3     */
      4     #include <stdio.h>
      5     #include <string.h>
      6     #include <stdlib.h>
      7     #include <mysql/mysql.h>
      8     #include <pthread.h>
      9     #include <unistd.h>
     10     #include <queue>
     11     #include <string>
     12 
     13     #define THREAD_NUM  4
     14     #define DBHOST      "localhost"
     15     #define DBUSER      "pca"
     16     #define DBPASS      "pca"
     17     #define DBPORT      3306
     18     #define DBNAME      "dxponline"
     19     #define DBSOCK      NULL //"/var/lib/mysql/mysql.sock"
     20     #define DBPCNT      0
     21 
     22     using namespace std;
     23 
     24     class CBlockQueue;
     25     typedef struct ThreadArgsST
     26     {
     27         int id;
     28         pthread_t *thread_id;
     29         CBlockQueue *pQueue;
     30     } ThreadArgs;
     31 
     32     class CMutex
     33     {
     34     public:
     35         CMutex()
     36         {
     37             pthread_mutex_init(&_mutex, NULL);
     38         }
     39         ~CMutex()
     40         {
     41             pthread_mutex_destroy(&_mutex);
     42         }
     43 
     44         int32_t lock()
     45         {
     46             return pthread_mutex_lock(&_mutex);
     47         }
     48 
     49         int32_t unlock()
     50         {
     51             return pthread_mutex_unlock(&_mutex);
     52         }
     53 
     54         int32_t trylock()
     55         {
     56             return pthread_mutex_trylock(&_mutex);
     57         }
     58 
     59     private:
     60         pthread_mutex_t _mutex;
     61     };
     62 
     63     class CGlobalFunction
     64     {
     65     public:
     66         static MYSQL *connect()
     67         {
     68             unsigned int timeout = 3000;
     69             mysql_thread_init();
     70             MYSQL *mysql = mysql_init(NULL);
     71 
     72             if (mysql == NULL)
     73             {
     74                 printf("mysql init failed: %s
    ", mysql_error(mysql));
     75                 return NULL;
     76             }
     77 
     78             mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
     79 
     80             if (mysql_real_connect(mysql, DBHOST, DBUSER, DBPASS, DBNAME, DBPORT, DBSOCK, DBPCNT) == NULL)
     81             {
     82                 printf("connect failed: %s
    ", mysql_error(mysql));
     83                 mysql_close(mysql);
     84                 mysql_thread_end();
     85                 return NULL;
     86             }
     87 
     88             printf("connect succssfully
    ");
     89             return mysql;
     90         }
     91     };
     92 
     93     class CBlockQueue : public CMutex
     94     {
     95     public:
     96         CBlockQueue() : _size(512)
     97         {
     98         }
     99         ~CBlockQueue()
    100         {
    101         }
    102         void set_size(int size)
    103         {
    104             _size = size;
    105         }
    106         int size()
    107         {
    108             this->lock();
    109             int size = q.size();
    110             this->unlock();
    111             return size;
    112         }
    113         bool push(void *m)
    114         {
    115             this->lock();
    116             // TODO
    117             /*
    118             if (q.size() > _size)
    119             {
    120                 this->unlock();
    121                 fprintf(stderr, "[QUEUE_IS_FULL]queue size over limit from push: %d
    ", _size);
    122                 return false;
    123             }
    124             */
    125             q.push(m);
    126             this->unlock();
    127             return true;
    128         }
    129 
    130         void *pop()
    131         {
    132             this->lock();
    133 
    134             if (q.empty())
    135             {
    136                 this->unlock();
    137                 fprintf(stderr, "[QUEUE_IS_EMPTY]queue is no item from pop");
    138                 return NULL;
    139             }
    140 
    141             void *m = q.front();
    142             q.pop();
    143             this->unlock();
    144             return m;
    145         }
    146 
    147     private:
    148         queue q;
    149         int _size;
    150     };
    151 
    152     void *func(void *arg)
    153     {
    154         ThreadArgs *args = (ThreadArgs *)arg;
    155         MYSQL_RES *result;
    156         MYSQL_ROW row;
    157         MYSQL_FIELD *field;
    158         bool pushed = true;
    159         unsigned int num_fields;
    160         unsigned int i;
    161         const char *pStatement = "SHOW TABLES";
    162         MYSQL *db = (MYSQL *)args->pQueue->pop();
    163 
    164         if (db == NULL)
    165         {
    166             db = CGlobalFunction::connect();
    167 
    168             if (db == NULL)
    169             {
    170                 printf("[%ld][%d]mysql connect failed
    ", *args->thread_id, args->id);
    171                 return (void *)0;
    172             }
    173         }
    174 
    175         if (0 != mysql_real_query(db, pStatement, strlen(pStatement)))
    176         {
    177             printf("[%ld][%d]query failed: %s
    ", *args->thread_id, args->id, mysql_error(db));
    178             args->pQueue->push(db);
    179             return (void *)0;
    180         }
    181 
    182         result = mysql_store_result(db);
    183 
    184         if (result == NULL)
    185         {
    186             printf("[%ld][%d]fetch result failed: %s
    ", *args->thread_id, args->id, mysql_error(db));
    187             args->pQueue->push(db);
    188             return (void *)0;
    189         }
    190 
    191         num_fields = mysql_num_fields(result);
    192         printf("[%ld][%d]numbers of result: %d
    ", *args->thread_id, args->id, num_fields);
    193 
    194         while (NULL != (field = mysql_fetch_field(result)))
    195         {
    196             printf("[%ld][%d]field name: %s
    ", *args->thread_id, args->id, field->name);
    197         }
    198 
    199         while (NULL != (row = mysql_fetch_row(result)))
    200         {
    201             unsigned long *lengths;
    202             lengths = mysql_fetch_lengths(result);
    203 
    204             for (i = 0; i < num_fields; i++)
    205             {
    206                 printf("[%ld][%d]{%.*s} ", *args->thread_id, args->id, (int) lengths[i], row[i] ? row[i] : "NULL");
    207             }
    208 
    209             printf("
    ");
    210         }
    211 
    212         mysql_free_result(result);
    213         args->pQueue->push(db);
    214         return (void *)0;
    215     }
    216 
    217     int main(int argc, char *argv[])
    218     {
    219         CBlockQueue queue;
    220         int thread_num;
    221 
    222         if (argc == 2)
    223         {
    224             thread_num = atoi(argv[1]);
    225         }
    226         else
    227         {
    228             thread_num = THREAD_NUM;
    229         }
    230 
    231         mysql_library_init(0, NULL, NULL);
    232         printf("argc: %d and thread_num: %d
    ", argc, thread_num);
    233 
    234         do
    235         {
    236             int i;  
    237             pthread_t *pTh = new pthread_t[thread_num];
    238             ThreadArgs *pArgs = new ThreadArgs[thread_num];
    239 
    240             for (i = 0; i < thread_num; i ++)
    241             {
    242                 pArgs[i].id = i;
    243                 pArgs[i].thread_id = &pTh[i];
    244                 pArgs[i].pQueue = &queue;
    245 
    246                 if (0 != pthread_create(&pTh[i], NULL, func, &pArgs[i]))
    247                 {
    248                     printf("pthread_create failed
    ");
    249                     continue;
    250                 }
    251             }
    252 
    253             for (i = 0; i < thread_num; i ++)
    254             {
    255                 pthread_join(pTh[i], NULL);
    256             }
    257 
    258             delete[] pTh;
    259             delete[] pArgs;
    260             int qsize = queue.size();
    261 
    262             for (i = 0; i < qsize; i ++)
    263             {
    264                 MYSQL *db = (MYSQL *)queue.pop();
    265 
    266                 if (NULL != db)
    267                 {
    268                     mysql_close(db);
    269                     mysql_thread_end();
    270                 }
    271             }
    272         }
    273         while (0);
    274 
    275         mysql_library_end();
    276         return 0;
    277     }
    • 执行

      make muti_thread_mysql_client_pool LDFLAGS="-g -O2 -L/usr/lib64/mysql -lmysqlclient -lpthread -lz -lm -lssl -lcrypto -ldl"

      即可获得对应单线程二进制。

    • 上述代码就是利用队列来保持mysql连接,达到优化连接数。

    总结

    • mysql连接与多线程处理不好,可能会造成很多问题,如

      • *MySQL Connection failed (#2058): This handle is already connected. Use a separate handle for each connection.*
      • Error in my_thread_global_end(): 1 threads didn't exit
      • 甚至出现coredump
    • 关于多线程连接mysql优化的思想,其实可以扩展到其他连接,如HTTP、Socket等连接中;

    测试多线程连接Mysql:

     1 int main()  
     2 {  
     3     mysql_library_init(0,NULL,NULL);  
     4     pthread_t producer;  
     5     pthread_t consumer_1;  
     6     pthread_t consumer_2;  
     7 //produce_fun不涉及数据库链接,不贴出来  
     8     pthread_create(&producer,NULL,produce_fun,NULL);  
     9     pthread_create(&consumer_1,NULL,consume_fun,NULL);  
    10     pthread_create(&consumer_2,NULL,consume_fun,NULL);  
    11 //下面的三句非常重要,main线程等待其他三个线程的结束,避免main线程执行到mysql_library_end时退出,而  
    12 //其他三个线程仍然在运行并报错的情形  
    13     pthread_join(producer,NULL);  
    14     pthread_join(consumer_1,NULL);  
    15     pthread_join(consumer_2,NULL);  
    16     mysql_library_end();  
    17     return 0;  
    18 }  
    19   
    20 void addRecord_d(MYSQL *ptr_db,const char *t_name,int item){  
    21     char query_buffer[100];  
    22     sprintf(query_buffer,"insert into %s values(0,%d)",t_name,item);  
    23     int ret=mysql_query(ptr_db,query_buffer);  
    24     if(ret){  
    25         fprintf(stderr,"%s%s
    ","cannot add record to ",t_name);  
    26         return;  
    27     }  
    28   
    29     unsigned long long update_id=mysql_insert_id(ptr_db);  
    30     printf("add record (%llu,%d) ok.",update_id,item);  
    31 }  
    32   
    33 void * consume_fun(void *arg){  
    34     MYSQL db;  
    35     MYSQL *ptr_db=mysql_init(&db);  
    36     mysql_real_connect();  
    37    //蓝色部分可以改为其他任何带操作数据库语句的代码  
    38     //procedure  
    39     while(1){  
    40         printf("consumer...");  
    41         int item=consume(&p);  
    42         addRecord_d(ptr_db,"test",item);  
    43     }  
    44    mysql_thread_end();  
    45     pthread_exit(NULL);  
    46 }  

    C/C++中调用api设置mysql连接的编码方式

    mysql在C/C++中调用api设置连接mysql的编码方式有以下几种方法:

    1. mysqli_set_charset
    调用示例:

    1. ret = mysql_set_character_set(mysql, "utf8");  

    说明:
    推荐使用的设置方法,与mysql的连接断开自动重连后仍能保持设置的编码格式,并且影响mysql_real_escape_string函数功能,使mysql_real_escape_string函数使用设置的编码格式转义字符串。
    但该函数在mysql5.0.5版本以后才支持,故版本太低者...。
    2. 执行sql语句:SET NAMES
    调用示例:

    1. ret = mysql_real_query(mysql, "SET NAMES UTF8;",   
    2.  (unsigned long) strlen ("SET NAMES UTF8;"));  

    说明:
    使用sql语句执行,只能影响当前与数据库的连接,断开自动重连后编码格式会重置为默认的配置。
    3. 设置MYSQL_SET_CHARSET_NAME属性
    调用示例:

    1. ret = mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");  

    说明:
    跟mysql_set_character_set类似,断开自动重连后仍能保持设置的编码格式,只是不会影响到mysql_real_escape_string函数。
    并且在mysql5.0.5版本都可以使用,低版本可以使用该方法代替。
    需要特别说明的是只有在调用mysql_real_connect连接数据库之前修改该属性才会生效。

    mysql控制自动重连行为

    当向mysql server发送statement时,mysql客户端发现连接失效后会自动尝试重新连接server。如果"自动重连"状态是enabled,客户端尝试连接server,并在连接成功后重新发送statement.

    "自动重连“默认是disabled的。

    如果应用程序需要知道连接是否可用(可以退出程序或显示相应的提示信息),确认“自动重连”是disabled。可以通过调用包含MYSQL_OPT_RECONNECT参数的mysql_options()函数以确认"自动重连"是否disabled:

    my_bool reconnect = 0;
    mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);
    

    如果连接已经断开,mysql_ping()依赖“自动重连”的状态。如果“自动重连”是enabled,mysql_ping()会重新获取连接。否则,会返回错误。

    有些客户端程序可能提供了控制自动重连的功能。比如,mysql默认是允许重连的,但是使用 --skip-reconnect 选项将关闭这个行为。

    如果发生了自动重连(比如,调用了mysql_ping()),自动重连是透明的。为了检查是否发生了重连,在调用mysql_ping()函数前,先调用mysql_thread_id()函数获取原始的连接id,然后调用mysql_ping(),在调用 mysql_thread_id()函数,对比两次 mysql_thread_id()的结果是否变化了。

    “自动重连”很方便,因为你不需要再实现自己重连代码,但是一旦发生了自动重连,connection的一些状态在server端就会被重置,而你的应用程序得不到这些变化的通知。

    下面列出连接相关的状态变化:

    • 任何未提交的事务将会回滚并且连接autocommit属性将会重置

    • 事务中的锁将会被释放。

    • 所有的临时表将会关闭(并释放)。

    • Session中的变量会重新初始化为系统默认值,包括在statements中显式声明的变量,比如SET NAMES

    • 用户自定义的变量将会丢失。

    • Prepared statements将释放。

    • HANDLER 变量将会关闭。

    • LAST_INSERT_ID()的值将会重置为0.

    • 通过GET_LOCK()获取的锁将会释放。

    如果连接失效,可能connection的session在server端依然在运行,当server没有检测到客户端失去连接。在这种情况下,原来connection的锁依然属于那个session,你可以调用mysql_kill()函数kill掉它。

    Linux下C语言连接MySQL找不到mysql.h解决办法

    昨天是把MySQL装上去了,今天尝试用C语言访问连接MySQL,发现使用编译指令:gcc -I/usr/include/mysql connect.c -lmysqlclient -o connect之后,提示找不到“mysql.h”文件,T_T|||。

           原因其实很简单了,昨天我只装了server和client两个包,对于平常的使用,这已经足够了,但对于要在Linux下进行数据库的开发,则还需要安装devel开发包,并且该开发包的版本应该和我之前所安装的server和client包版本一致,否则会发生冲突而导致无法安装。

           server和client包的安装见上一篇日志:Linux(Fedora 9)卸载自带的MySQL并安装MySQL的详细步骤

           好了,我们来安装devel包,注意版本要保持一致:

     
    1. [root@localhost install]# rpm -ivh MySQL-devel-community-5.1.46-1.rhel5.i386.rpm   
    2. Preparing...                ########################################### [100%]  
    3.    1:MySQL-devel-community  ########################################### [100%]  

           这次为了避免再出现问题,我把共享组件包shared也装上去了,哈哈:

     
    1. [root@localhost install]# rpm -ivh MySQL-shared-community-5.1.46-1.rhel5.i386.rpm   
    2. Preparing...                ########################################### [100%]  
    3.    1:MySQL-shared-community ########################################### [100%]  

           装完之后,再编译就通过了,此时的“mysql.h”已经出现在了/usr/include/mysql目录下面。Happy~

    undefined reference to `mysql_init'解决办法

    写了一个很简单的测试数据库连接的程序conn.c如下:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include "/usr/local/mysql/include/mysql/mysql.h"
     4 #include <string.h>
     5 int main(int argc, char *argv[])
     6 {
     7 MYSQL my_connection;
     8 mysql_init(&my_connection);
     9 if (mysql_real_connect(&my_connection, "localhost", "root", "","mysql",0,NULL,CLIENT_FOUND_ROWS))
    10 {
    11     printf("Connection success
    "); 
    12     mysql_close(&my_connection);
    13 }
    14 else
    15 {
    16     fprintf(stderr, "Connection failed
    ");
    17     if (mysql_errno(&my_connection))
    18     {
    19         fprintf(stderr, "Connection error %d: %s
    ",mysql_errno(&my_connection),mysql_error(&my_connection));
    20         }
    21 }
    22     return EXIT_SUCCESS;
    23 }

    gcc编译:gcc -o conn conn.c出现如下错误:
    /tmp/ccY0JTdh.o(.text+0x1e): In function `main':
    : undefined reference to `mysql_init'
    /tmp/ccY0JTdh.o(.text+0x47): In function `main':
    : undefined reference to `mysql_real_connect'
    /tmp/ccY0JTdh.o(.text+0x6d): In function `main':
    : undefined reference to `mysql_close'
    /tmp/ccY0JTdh.o(.text+0x97): In function `main':
    : undefined reference to `mysql_errno'
    /tmp/ccY0JTdh.o(.text+0xad): In function `main':
    : undefined reference to `mysql_error'
    /tmp/ccY0JTdh.o(.text+0xc0): In function `main':
    : undefined reference to `mysql_errno'
    collect2: ld returned 1 exit status
    出现该错误的原因是因为编译器找不到mysql_init,mysql_close等的具体实现.虽然我们包括了正确的头文件,但是 我们在编译的时候还是要连接确定的库.对于一些常用的函数的实现,gcc编译器会自动去连接一些常用库,这样我们就没有必要自己去指定了,如:printf函数.在本程序中要通过-L选项包含库文件的路径:
    gcc -o conn conn.c -L /usr/local/mysql/lib/*.a -lz
    通过,
    用*.a将库全部包含进来拉,其实只要包含mysqlclient.a就可以. -lz什么意思我也不清楚了

    undefined reference to 'dlopen';undefined reference to 'dlclose';undefined reference to 'dlerror'等问题

    在linux下,编译链接的时候,经常会遇到这样一个问题,undefined reference to.....,引起这个问题的原因在于在链接的时候缺少选项。下面举几个例子,并给出解决办法。

    1、undefined reference to `dlerror'

     undefined reference to `dlopen'

     undefined reference to `dlerror';;解决方法:在makefile的 ldflags 后面把选项 -ldl添加上即可

    2、undefined reference to `main';;解决方法:在makefile的 ldflags 后面添加 -nostartfiles 选项

    3、undefined reference to `pthread_setspecific'

       undefined reference to `pthread_key_delete'

         undefined reference to `pthread_key_create'::解决办法:在makefile的LDFLAGS后面添加 -lpthread 选项。

    最后::如果undefined reference to后面的内容是在自己的文件中声明或定义的东西,就不能用这种方法来解决了。这时就需要检查一下自己的makefile涉及到源文件、头文件的地方是否出错了,也有可能是其他的原因

  • 相关阅读:
    C#博客随笔之四:使用C#模拟办公网登录HttpClient的使用
    C#博客随笔之三:Linq in C#
    C#博客随笔之二:wp开发之弹出对话框
    C#博客随笔之一:使用C#的第一个WP程序
    Fedora15命令速查手册
    乐观是一种智慧
    完全教程 Aircrackng破解WEP、WPAPSK加密利器
    FreeBSD常用命令大全
    Linux 网络管理员指南——前言
    API
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/8039801.html
Copyright © 2020-2023  润新知