C++ から Django 関数を呼び出し、その出力を C++ コードで取得する必要があります。ご存じのように、Django は、必要な関数を最初のパラメーターとして使用し、その後に引数を指定して Manage.py Python スクリプトを呼び出すことによって使用されます。
現在、JSON 形式の文字列を返す「test」という名前のテスト関数があります。
したがって、私が電話すると:
python manage.py test
私は次のようになります:
{'products': [{'id': 125, 'label': 'Robin'}, {'id': 4, 'label': 'Robinou'}]}
これを cpp で取得するには、次のことができます。
system(python path.../manage.py test);
出力をキャッチします。しかし、私はそれが好きではありません。Boost.Python も使用できます。私も好きじゃない。
サイズと速度を考慮して、これを C++/Python.h でのみ実行できるようにしたいと考えています。
これは私が実行しているmanage.pyです:
import os
import sys
sys.path.append('C:\ds')
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "frontoffice.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
を追加するprint sys.argv
と、次の出力が得られます: ['manage.py', 'test']
.
だから私は厄介な方法でそれを行うことができました:
bool initPython()
{
Py_Initialize();
int check = 0;
check = PyRun_SimpleString("import sys");
check = PyRun_SimpleString("import os");
check = PyRun_SimpleString("sys.path.append('C:\\ds')");
check = PyRun_SimpleString("os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"frontoffice.settings\")");
check = PyRun_SimpleString("from django.core.management import execute_from_command_line");
if(check == 0) return true;
else return false;
}
std::string execPythonCommand(std::string cmd)
{
std::string command = std::string("robin = ['dontreallycarewhatitis', '").append(cmd).append("']");
PyRun_SimpleString(command.c_str());
PyRun_SimpleString("execute_from_command_line(robin)");
}
派手なものはありません。クロスプラットフォームであるという利点がありますが、出力をキャッチするのは面倒なので、機能しますが、私が探しているものではありません。execute_from_comand_line コマンドの出力を直接取得できるようにしたいと考えています。
これが私がこれまでに思いついたものです。initPython() を実行した後:
PyObject* executeCmd = PyImport_Import(PyString_FromString("django.core.management"));
PyObject* executeFunc = PyObject_GetAttrString(executeCmd, "execute_from_command_line");
std::cout << "Imported function." << " isNULL: " << (executeFunc == NULL) << " isExecutable: " << PyCallable_Check((executeFunc)) << std::endl;
だから私は execute_from_command_line 関数の Cpp オブジェクトを取得することができました - そしてそれは呼び出し可能です。ここがややこしいところです。どうやって呼ぶの?
Python Documentation によると、sys.argv はリストです。そこで、まったく同じものを再作成して呼び出してみました:
PyObject* pRobin = PyList_New(2);
PyObject* pString = PyString_FromString("test");
PyObject* pString0 = PyString_FromString("manage.py");
PyList_Append(pRobin,pString0);
PyList_Append(pRobin,pString);
PyObject* pValue = PyObject_CallObject(executeFunc, pRobin);
//PyObject* pValue = PyObject_CallFunctionObjArgs(executeFunc, pRobin, NULL); //Doesn't work either
今、私はすべてを試しました。リストの代わりにタプルを使用する PyObject_CallObject、CallFunction、CallFunctionObjArgs、および PyErr_Print() は私に明示的なものを何も与えません。私はPythonの専門家ではなく、この問題に苦しんでいます。テスト ルーチンの出力 JSON 文字列を格納する pValue を取得するにはどうすればよいですか?
ご参考までに:
>>> inspect.getargspec(django.core.management.execute_from_command_line)
ArgSpec(args=['argv'], varargs=None, keywords=None, defaults=(None,))
やがて、manage.py xxx (xxx はコマンド) を頻繁かつ迅速に実行する必要があるため、面倒な stdio キャッチを行うよりも C/API を使用したいと考えています。
参考までに、私は VS2012、Windows 8、Python 2.7、および PostGRE を使用しています。どんなアイデアでも大歓迎です。ありがとう!