繁体   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