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\n", mysql_error(mysql));
35             mysql_close(mysql);
36             mysql_library_end();
37             return 0;
38         }
39 
40         printf("connect succssfully\n");
41 
42         if (0 != mysql_real_query(mysql, pStatement, strlen(pStatement)))
43         {
44             printf("query failed: %s\n", 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\n", 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\n", num_fields);
62 
63         while (NULL != (field = mysql_fetch_field(result)))
64         {
65             printf("field name: %s\n", 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("\n");
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\n", *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\n", *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\n", *args->thread_id, args->id);
 56 
 57         if (0 != mysql_real_query(mysql, pStatement, strlen(pStatement)))
 58         {
 59             printf("[%ld][%d]query failed: %s\n", *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\n", *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\n", *args->thread_id, args->id, num_fields);
 77 
 78         while (NULL != (field = mysql_fetch_field(result)))
 79         {
 80             printf("[%ld][%d]field name: %s\n", *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("\n");
 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\n", 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\n");
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\n", 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\n", mysql_error(mysql));
 83                 mysql_close(mysql);
 84                 mysql_thread_end();
 85                 return NULL;
 86             }
 87 
 88             printf("connect succssfully\n");
 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\n", _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\n", *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\n", *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\n", *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\n", *args->thread_id, args->id, num_fields);
193 
194         while (NULL != (field = mysql_fetch_field(result)))
195         {
196             printf("[%ld][%d]field name: %s\n", *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("\n");
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\n", 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\n");
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\n","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\n"); 
12     mysql_close(&my_connection);
13 }
14 else
15 {
16     fprintf(stderr, "Connection failed\n");
17     if (mysql_errno(&my_connection))
18     {
19         fprintf(stderr, "Connection error %d: %s\n",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涉及到源文件、頭文件的地方是否出錯了,也有可能是其他的原因

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM