簡體   English   中英

如何在C中同時使用GTK和libcurl?

[英]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”。 當前,您有三個庫:

  • Gtk +
  • 卷曲
  • cJSON

可能以任意方式互動。 您需要檢查的內容:

  • 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM