简体   繁体   English

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

[英]How to use GTK and libcurl at the same time in C?

I'm trying to develop an application in C with GTK for the GUI, libcurl to get data by a web API and cJSON to parse JSON. 我正在尝试使用GTK开发用于GUI的C语言应用程序,libcurl以通过Web API获取数据以及cJSON来解析JSON。

My problem is that when I do my request with libcurl after gtk_init, the data that I get can not be parsing in JSON. 我的问题是,当我在gtk_init之后用libcurl发出请求时,无法在JSON中解析所获取的数据。 Otherwise, if I get the data and parse it before gtk_init, the parsing works fine. 否则,如果我得到数据并在gtk_init之前对其进行解析,则解析工作正常。

I have an example to demonstrate it, the first printf in the main returns the JSON correctly but the second printf which is after gtk_init returns NULL (to be exact, the parsing stops at the first decimal number and fail) : 我有一个示例来演示它,主函数中的第一个printf正确返回JSON,但是在gtk_init之后的第二个printf返回NULL(确切地说,解析在第一个十进制数处停止并失败):

initString : 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 : 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;
}

My function to get data with libcurl : 我用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;
}

The main : 主要的 :

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;
}

I have tried to resolve this by creating threads with g_idle_add, gdk_threads_idle_add, gdk_threads_entry and gdk_threads_leave, pthread_create and pthread_join but nothing worked. 我试图通过使用g_idle_add,gdk_threads_idle_add,gdk_threads_entry和gdk_threads_leave,pthread_create和pthread_join创建线程来解决此问题,但没有任何效果。

Does someone know how to resolve this problem ? 有人知道如何解决这个问题吗?

Thanks. 谢谢。

You need to narrow down your problem. 您需要缩小问题范围。 In other words, you need "M" in MVCE . 换句话说,您需要在MVCE中使用 “ M”。 Currently you have three libraries: 当前,您有三个库:

  • Gtk+ Gtk +
  • cURL 卷曲
  • cJSON cJSON

that might interact in arbitrary ways. 可能以任意方式互动。 What you need to check: 您需要检查的内容:

  • Does cURL return different data before and after gtk_init call? cURL在gtk_init调用之前和之后是否返回不同的数据? If no, then problem is not with cURL. 如果不是,则问题不在于cURL。

  • If you hardcode JSON data in your program and parse it with cJSON, are results different before and after gtk_init ? 如果您在程序中对JSON数据进行硬编码并使用cJSON进行解析,则gtk_init之前和之后的结果是否有所不同? If so, problem is in cJSON. 如果是这样,则问题出在cJSON中。 If no, problem is not related to cJSON. 如果不是,则问题与cJSON无关。


My guess is as follows. 我的猜测如下。 gtk_init does several things, amongst them sets locale . gtk_init做几件事,其中包括设置locale Since you fetch data from .fr domain, I assume that you have French locale set on your computer. 由于您是从.fr域中获取数据的,因此我假设您在计算机上设置了法语语言环境。

to be exact, the parsing stops at the first decimal number and fail 确切地说,解析会在第一个十进制数处停止并失败

In French, decimal separator is comma , instead of period . 在法语中,小数点分隔符是逗号,而不是period . , so I suppose that after GTK+ changes locale, cJSON starts to look for , in decimal numbers but it finds . ,所以我想,GTK +改变区域后,cJSON开始寻找,在十进制的数字,但它发现. and fails. 并失败了。

Possible solutions 可能的解决方案

  • As a workaround, call gtk_disable_setlocale before gtk_init . 解决方法是,在gtk_init之前调用gtk_disable_setlocale This might cause unintended consequences, eg. 这可能会导致意想不到的后果,例如。 your program starts to display numbers in English format instead of French in its UI. 您的程序开始在其UI中以英文格式而不是法语显示数字。

  • The real solution would be to raise bug in cJSON, as JSON parsing should not take locale into account when parsing numbers. 真正的解决方案是在cJSON中引发错误,因为在解析数字时JSON解析不应考虑语言环境。 JSON mandates period . JSON强制期限. as decimal separator. 作为小数点分隔符。

I doubt very much that this has anything at all to do with the gtk_init() call. 我非常怀疑这与gtk_init()调用有什么关系。 It sounds like memory corruption. 听起来像是内存损坏。 This would likely be the case eg if you returned a pointer to data that was allocated and then cleaned up by curl. 例如,如果您返回一个指向已分配数据的指针,然后通过curl进行清理,则可能是这种情况。 In this case both calls are wrong, you just happened to get away with it the first time as the memory was hanging around untouched in that case. 在这种情况下,两个呼叫都错了,因为这种情况下内存在周围徘徊,您只是碰巧第一次摆脱了它。 Check the API for function calls you make. 检查API进行的函数调用。 Some will allocate memory that needs to be freed, others don't. 有些会分配需要释放的内存,而有些则不需要。

I suggest you use build with -g and use gdb to test your code. 我建议您使用带有-g的build并使用gdb来测试您的代码。 This will help narrow down where the problem lies. 这将有助于缩小问题所在。 Take a look and see if the strings are identical. 看一下字符串是否相同。

cURL returns the same data before and after, I checked it by putting data in 2 strings and strcmp returns 0. cURL前后返回相同的数据,我通过将数据放入2个字符串中进行了检查,而strcmp返回0。

Indeed, I'm french and there may be a confusion between , and . 事实上,我是法国人,有可能是之间的混乱,. .

gtk_disable_setlocale solved my problem ! gtk_disable_setlocale解决了我的问题!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM