如何将结果从MySQL查询转换为C?中的JSON字符串?
当然我知道该怎么做,我只是想知道是否已经有了复制粘贴的解决方案,意识到我不想编写样板代码。
Google如何解决这个问题?谷歌只是忽略c
并显示PHP等的结果。
答案 0 :(得分:0)
我这样做的C文件比相应的PHP文件快四倍,使用ab
来衡量性能:
ab -k -c 300 -n 10000 localhost/tiny.php
Time per request: 393.072 [ms] (mean)
用C:
ab -k -c 300 -n 10000 localhost/cgi/tiny.fcgi
Time per request: 98.237 [ms] (mean)
这假设Apache产生了10个tiny.fcgi
进程,PHP不使用FastCGI。
FastCgiServer /var/www/cgi/tiny.fcgi -processes 10
这是PHP代码,它连接到MySQL,获取查询结果并回显JSON表示:
<?php
$mysqli = mysqli_connect("localhost", "user", "password", "db");
mysqli_set_charset($mysqli, "utf8");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$result = mysqli_query($mysqli, "SELECT * FROM table");
$rows = array();
while ($row = mysqli_fetch_assoc($result)) {
$rows[] = $row;
}
echo json_encode($rows);
让我们逐步完成C代码。我将使用PHP内部结构smart_str
来处理字符串(这是PHP在json_encode
函数中使用的)。对字符串使用天真char*
将是灾难性的,因为malloc
和free
的数量会因字符串附加用法而变得很大。
我们想使用FastCGI:
#include "fcgi_stdio.h"
int main(void)
{
while(FCGI_Accept() >= 0)
{
}
FCGI_Finish();
return 0;
}
使用valgrind
进行分析,结果仍然可以得到768个字节,我们将忽略它(可能是FastCGI中的错误)。
接下来是MySQL连接和查询:
MYSQL* connection = NULL;
MYSQL_RES* result = NULL;
connection = mysql_init(NULL);
if (connection == NULL)
{
(void) FCGI_fprintf(FCGI_stderr, "Could not connect to MySQL: %s\n", mysql_error(connection));
continue;
}
// Connect to database
if (mysql_real_connect(connection, "localhost", "user", "password", "db", 0, NULL, 0) == NULL)
{
close_mysql_with_error(connection);
continue;
}
// Select from pages
if (mysql_query(connection, "SELECT * FROM table") != 0)
{
close_mysql_with_error(connection);
continue;
}
// Get result
result = mysql_store_result(connection);
// Abort if no result
if (result == NULL)
{
close_mysql_with_error(connection);
continue;
}
(我使用continue
代替exit
或return
,因为此代码位于上面显示的while
循环中。)
这里没什么奇怪的,对吧?
下一部分将创建我们的smart_str
JSON变量,将其传递给函数result_to_json
,然后回显结果。
smart_str json = {0, 0, 0};
result_to_json(result, &json);
if (json.c != NULL)
(void) FCGI_printf("json = %s\n", json.c);
smart_str_free(&json);
result_to_json
只是MySQL结果中行的循环:
static void result_to_json(MYSQL_RES *result, smart_str* json)
{
MYSQL_ROW row;
int i;
int num_fields = (int) mysql_num_fields(result);
smart_str** fields = get_field_names(result, num_fields);
if (fields == NULL)
{
return;
}
smart_str_appendc(json, '[');
while ((row = mysql_fetch_row(result, num_fields)))
{
smart_str_appendl(json, "{", 1);
for (i = 0; i < num_fields; i++)
{
// key
smart_str_appendl(json, "\"", 1);
smart_str_appendl(json, fields[i]->c, fields[i]->len);
smart_str_appendl(json, "\": ", 3);
if (row[i] == NULL)
{
smart_str_appendl(json, "null", 4);
smart_str_appendl(json, ", ", 2);
}
else
{
smart_str_appendl(json, "\"", 1);
smart_str_appendl(json, row[i], strlen(row[i]));
smart_str_appendl(json, "\", ", 3);
}
}
if (json == NULL) {
free_field_names(fields, num_fields);
return;
}
// Strip last ','
json->len--;
json->len--;
smart_str_appendl(json, "}, ", 3);
}
if (json == NULL)
{
free_field_names(fields, num_fields);
return;
}
// Strip last ','
json->len--;
json->len--;
smart_str_appendl(json, "]", 1);
smart_str_0(json);
free_field_names(fields, num_fields);
return;
}
最后,get_field_names
和free_field_names
:
static smart_str** get_field_names(MYSQL_RES *my_result, int num_fields)
{
smart_str** fields; // Array of pointers
MYSQL_FIELD *field = NULL;
int i;
// Allocate size of array
fields = malloc(num_fields * sizeof(smart_str*));
if (fields == NULL)
{
return NULL;
}
for (i = 0; i < num_fields; i++)
{
field = mysql_fetch_field(my_result);
if (field == NULL) {
// TODO: Free fields[]
free(fields);
return NULL;
}
fields[i] = malloc(sizeof(smart_str));
if (fields[i] == NULL) {
// TODO: Free fields[]
free(fields);
return NULL;
}
else
{
fields[i]->c = NULL;
smart_str_appendl(fields[i], field->name, strlen(field->name));
}
return fields;
}
static void free_field_names(smart_str** strings, int size)
{
int i;
for (i = 0; i < size; i++)
{
smart_str_free(strings[i]);
free(strings[i]);
}
free(strings);
}
你去吧!剩下的工作就是针对启用了FastCGI的PHP进行测量,以了解PHP性能提高了多少。