在C 中使用Jinja2时,结果无效

invalid result when using jinja2 within c++

本文关键字:结果 无效 Jinja2      更新时间:2023-10-16

我使用此代码用于使用jinja2:

import json
from jinja2 import Template
def render_json(p_input_str, p_template_str, p_str):
    p_input = json.loads(p_input_str)
    t = Template(p_template_str)
    return t.render(input=p_input, str=p_str)

temp.json:

{
    "id" : "{{ input["id"] }}",
    "data" : [
        {% for item in input["list"] %}
        {
        "id" : "{{ item["id"] }}",
        "value" : "{{ item["data"] }}"
        },
        {% endfor %}
        null
    ],
    "str" : "{{ str }}",
    "ext" : "{{ input["x"] }}"
}

input.json:

{
    "id" : "1",
    "list" : [ { "id" : "2", "data" : "4" } ],
    "x" : "20"
}

使用python一切正常:

input_str=open("test.json").read()
template_str=open("temp.json").read()
print render_json(input_str, template_str, "1234")

输出:

{
    "id" : "1",
    "data" : [
        {
        "id" : "2",
        "value" : "4"
        },
        null
    ],
    "str" : "1234",
    "ext" : "20"
}

但是,当我尝试从C 调用render_json时,添加了input_str以输出:

{
    "id" : "1",
    "list" : [ { "id" : "2", "data" : "4" } ],
    "x" : "20"
}
{
    "id" : "1",
    "data" : [
        {
        "id" : "2",
        "value" : "4"
        },
        null
    ],
    "str" : "1234",
    "ext" : "20"
}

这是我用于嵌入python的C 代码:它基于将Python嵌入另一个应用程序

的Python文档
int main(int argc, char *argv[])
{
  std::stringstream buffer;
  std::ifstream t;
  t.open("test.json");
  buffer << t.rdbuf();
  std::string input_str = buffer.str();
  t.close();
  buffer.clear();
  t.open("temp.json");
  buffer << t.rdbuf();
  std::string template_str = buffer.str();
  std::vector<std::string> x = {input_str, template_str, "1234"};
  PyObject *pName, *pModule, *pDict, *pFunc;
  PyObject *pArgs, *pValue;
  if (argc < 3)
  {
    printf("Usage: exe_name python_source function_namen");
    return 1;
  }
  Py_Initialize();
  pName = PyString_FromString(argv[1]);
  /* Error checking of pName left out */
  pModule = PyImport_Import(pName);
  Py_DECREF(pName);
  if (pModule != NULL)
  {
    pFunc = PyObject_GetAttrString(pModule, argv[2]);
    /* pFunc is a new reference */
    if (pFunc && PyCallable_Check(pFunc))
    {
      pArgs = PyTuple_New(3);
      for (int i = 0; i < 3; ++i)
      {
        pValue = PyString_FromString(x[i].c_str());
        if (!pValue)
        {
          Py_DECREF(pArgs);
          Py_DECREF(pModule);
          fprintf(stderr, "Cannot convert argumentn");
          return 1;
        }
        /* pValue reference stolen here: */
        PyTuple_SetItem(pArgs, i, pValue);
      }
      pValue = PyObject_CallObject(pFunc, pArgs);
      Py_DECREF(pArgs);
      if (pValue != NULL)
      {
        printf("Result of call: %sn", PyString_AsString(pValue));
        Py_DECREF(pValue);
      }
      else
      {
        Py_DECREF(pFunc);
        Py_DECREF(pModule);
        PyErr_Print();
        fprintf(stderr,"Call failedn");
        return 1;
      }
    }
    else
    {
      if (PyErr_Occurred())
        PyErr_Print();
      fprintf(stderr, "Cannot find function "%s"n", argv[2]);
    }
    Py_XDECREF(pFunc);
    Py_DECREF(pModule);
  }
  else
  {
    PyErr_Print();
    fprintf(stderr, "Failed to load "%s"n", argv[1]);
    return 1;
  }
  Py_Finalize();
  return 0;
}

可以肯定的是,这与您从同一std::stringstreaminput_strtemplate_str构建有关,与您的Python或Bindings无关。也就是说,如果您只是 print template_str在调用python之前,您会在开始时看到已经具有 input_str的内容。

std::stringstream::clear不做您认为的事情 - 它只是从ios_base继承而来,并且清除了错误标志

只需使用第二个缓冲区即可。(或致电buffer.str(""),我 think 可以做您真正想要的事情,但这可能不值得可读性降低。(