[英]How to use GTK and libcurl at the same time in C?
我正在嘗試使用GTK開發用於GUI的C語言應用程序,libcurl以通過Web API獲取數據以及cJSON來解析JSON。
我的問題是,當我在gtk_init之后用libcurl發出請求時,無法在JSON中解析所獲取的數據。 否則,如果我得到數據並在gtk_init之前對其進行解析,則解析工作正常。
我有一個示例來演示它,主函數中的第一個printf正確返回JSON,但是在gtk_init之后的第二個printf返回NULL(確切地說,解析在第一個十進制數處停止並失敗):
initString:
void initString(String * s) {
s->len = 0;
s->ptr = malloc(s->len + 1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
writeFunc:
size_t writeFunc(void *ptr, size_t size, size_t nmemb, String * s)
{
size_t newLen = s->len + size*nmemb;
s->ptr = realloc(s->ptr, newLen + 1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr + s->len, ptr, size * nmemb);
s->ptr[newLen] = '\0';
s->len = newLen;
return size * nmemb;
}
我用libcurl獲取數據的功能:
char * getData(gpointer user_data)
{
curl_global_init(CURL_GLOBAL_ALL);
CURL * curl;
char * url = user_data;
CURLcode res;
String s;
struct curl_slist * headers = NULL;
curl = curl_easy_init();
if(curl)
{
initString(&s);
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
//curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, 6);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
//write data in a string
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
res = curl_easy_perform(curl);
}
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return s.ptr;
}
主要的 :
int main(int argc, char ** argv)
{
char * str;
cJSON * json;
str = getData("https://data.culture.gouv.fr/api/records/1.0/search/?dataset=liste-et-localisation-des-musees-de-france&facet=ville&sort=ville&facet=nomdep&refine.nomdep=AIN&rows=1");
json = cJSON_Parse(str);
printf("DATA : %s\n", cJSON_Print(json));//returns the JSON perfectly
gtk_init(&argc,&argv);
str = getData("https://data.culture.gouv.fr/api/records/1.0/search/?dataset=liste-et-localisation-des-musees-de-france&facet=ville&sort=ville&facet=nomdep&refine.nomdep=AIN&rows=1");
json = cJSON_Parse(str);
printf("ERROR : %s\n", cJSON_GetErrorPtr());//returns half of data
printf("DATA : %s\n", cJSON_Print(json));//returns NULL
gtk_main();
curl_global_cleanup();
return EXIT_SUCCESS;
}
我試圖通過使用g_idle_add,gdk_threads_idle_add,gdk_threads_entry和gdk_threads_leave,pthread_create和pthread_join創建線程來解決此問題,但沒有任何效果。
有人知道如何解決這個問題嗎?
謝謝。
您需要縮小問題范圍。 換句話說,您需要在MVCE中使用 “ M”。 當前,您有三個庫:
可能以任意方式互動。 您需要檢查的內容:
cURL在gtk_init
調用之前和之后是否返回不同的數據? 如果不是,則問題不在於cURL。
如果您在程序中對JSON數據進行硬編碼並使用cJSON進行解析,則gtk_init
之前和之后的結果是否有所不同? 如果是這樣,則問題出在cJSON中。 如果不是,則問題與cJSON無關。
我的猜測如下。 gtk_init
做幾件事,其中包括設置locale 。 由於您是從.fr
域中獲取數據的,因此我假設您在計算機上設置了法語語言環境。
確切地說,解析會在第一個十進制數處停止並失敗
在法語中,小數點分隔符是逗號,
而不是period .
,所以我想,GTK +改變區域后,cJSON開始尋找,
在十進制的數字,但它發現.
並失敗了。
解決方法是,在gtk_init
之前調用gtk_disable_setlocale
。 這可能會導致意想不到的后果,例如。 您的程序開始在其UI中以英文格式而不是法語顯示數字。
真正的解決方案是在cJSON中引發錯誤,因為在解析數字時JSON解析不應考慮語言環境。 JSON強制期限.
作為小數點分隔符。
我非常懷疑這與gtk_init()調用有什么關系。 聽起來像是內存損壞。 例如,如果您返回一個指向已分配數據的指針,然后通過curl進行清理,則可能是這種情況。 在這種情況下,兩個呼叫都錯了,因為這種情況下內存在周圍徘徊,您只是碰巧第一次擺脫了它。 檢查API進行的函數調用。 有些會分配需要釋放的內存,而有些則不需要。
我建議您使用帶有-g的build並使用gdb來測試您的代碼。 這將有助於縮小問題所在。 看一下字符串是否相同。
cURL前后返回相同的數據,我通過將數據放入2個字符串中進行了檢查,而strcmp返回0。
事實上,我是法國人,有可能是之間的混亂,
和.
。
gtk_disable_setlocale
解決了我的問題!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.