最近、プロジェクトのニーズにより、x265でPythonスクリプトを呼び出し、一般的な使用プロセスを記録する必要があります。
1つ、コンパイル
x265 / VTM / HMをコンパイルするときは、CMakeLists.txtに次のステートメントを追加する必要があります。
# python3
include_directories("D:/Anaconda/include/")
link_libraries("D:/Anaconda/libs/python36.lib")
Anacondaをダウンロードしたので、ここに含める必要があるのはAnacondaの下のパスです。追加後、通常どおりコンパイルします
2つ目は、C ++がPythonスクリプトを呼び出すことです。
コンパイルが完了したら、VS2017でプロジェクトを開きます
1.Pythonヘッダーファイルを追加します
#include<Python.h>
2. pythonライブラリ関数を使用する前に、pythonインターフェイスを初期化する必要があります
Py_Initialize();
同様に、Pythonスクリプトを呼び出した後、Pythonインターフェイスを解放することを忘れないでください。
Py_Finalize();
注:初期化と解放のこれら2つの関数は、プログラム全体で1回しか呼び出すことができないため、プログラム全体の最初と最後に配置する必要があります。複数の呼び出しがある場合は、アクセスの競合が発生する可能性があります。 dllが見つかりません。など。
3.Pythonスクリプトの下で作業パスを切り替えます
PyRun_SimpleString("import sys");
PyRun_SimpleString("import os");
PyRun_SimpleString("os.chdir('./Net')");
PyRun_SimpleString("sys.path.append('./')");
ここでは、os.chdirを使用してPythonスクリプトが配置されているパスに切り替えてから、sys.path.append( './')を使用して現在のディレクトリを作業パスに追加します
呼び出しが完了したら、os.chdirを使用して前の作業ディレクトリに切り替えます
4.モジュールと関数をロードします
m_pMod = PyImport_ImportModule("testnet");
if (!m_pMod)
{
PyErr_Print();
}
m_pFunc = PyObject_GetAttrString(m_pMod, "run");
if (!m_pFunc)
{
PyErr_Print();
}
ここで呼び出すPythonスクリプトの名前はtestnet.pyファイルなので、PyImport_ImportModule関数を使用してPythonファイルを呼び出し、次にPyObject_GetAttrStringを使用して対応する関数を呼び出します。ここで、runはテストネットで定義されたPython関数名です。 .pyファイル
注:スクリプトと関数を引用するたびに、 PyErr_Print()関数を使用してエラーをチェックする必要があります。
5.パラメーターを設定し、パラメーターをpython関数に渡し、python関数を呼び出します。
PyObject *pReturn = NULL;
PyObject *pInputRec = PyList_New(TuWidth * TuHeight);
PyObject *pParam = PyTuple_New(3);
for (int row = 0; row < TuHeight; row++)
{
for (int col = 0; col < TuWidth; col++)
{
PyList_SetItem(pInputRec, row * TuWidth + col, Py_BuildValue("i", NNRecon[row * TuWidth + col]));
}
}
PyTuple_SetItem(pParam, 0, pInputRec);
PyTuple_SetItem(pParam, 1, Py_BuildValue("i", TuWidth));
PyTuple_SetItem(pParam, 2, Py_BuildValue("i", TuHeight));
pReturn = PyEval_CallObject(m_pFunc, pParam);//调用python中函数
PyList_Check(pReturn);
我々が使用することができPyList_Newの、Pythonのリストを定義する関数をPyTuple_Newの、Pythonのタプルを定義する関数をPy_BuildValueする」に加え、「I」は、PythonオブジェクトへのC ++タイプ番号を変換する変換フォーマット(整数)の機能をi "次の形式があります。
- "s"(string)[char *]:C文字列をPythonオブジェクトに変換します。C文字列が空の場合は、NONEを返します。
- "s#"(string)[char *、int]:C文字列とその長さをPythonオブジェクトに変換します。C文字列がnullポインターの場合、長さは無視され、NONEが返されます。
- "z"(文字列またはなし)[char *]:作用同 "s"。
- "z#"(文字列またはなし)[char *、int]:作用同 "s#"。
- "i"(integer)[int]:C型intをPythonintオブジェクトに変換します。
- "b"(整数)[char]:作用同 "i"。
- "h"(整数)[short int]:作用同 "i"。
- "i"(integer)[long int]:タイプCのlongをPyhonのintオブジェクトに変換します。
- "c"(長さ1の文字列)[char]:Cタイプのcharを長さ1のPython文字列オブジェクトに変換します。
- "d"(float)[double]:PythonでCdoubleを浮動小数点オブジェクトに変換します。
- "f"(float)[float]:作用同 "d"。
- 「O&」(オブジェクト)[コンバーター、何でも]:変換関数を使用して任意のデータ型をPythonオブジェクトに変換し、これらのデータは変換関数のパラメーターとして使用されます
PyList_SetItem関数を使用して、リスト内の要素の値を設定します。最初のパラメーターは設定するリスト、2番目のパラメーターはリストのインデックス値、3番目のパラメーターは設定する値を示します。同様に、PyTuple_SetItem関数はタプルに値を設定できます
パラメータを設定した後、PyEval_CallObject関数を使用してPython関数を呼び出し、パラメータを渡します。最初のパラメータは呼び出される関数を参照し、2番目のパラメータは関数のパラメータを参照します。
私が定義したrun関数はPythonリストを返すため、Pythonの戻り値を取得した後、PyList_Check関数を呼び出して、それがPythonリスト(リスト)であるかどうかを判断します。
6.戻り値を解析し、PythonオブジェクトをC ++タイプに変換します
for (int row = 0; row < TuHeight; row++)
{
for (int col = 0; col < TuWidth; col++)
{
PyArg_Parse(PyList_GetItem(pReturn, row * TuWidth + col), "i", &NNRecon[row * TuWidth + col]);
}
}
PyList_GetItem関数は、Pythonリスト内の対応するインデックスの値を取得できます。最初のパラメーターはPythonリストを表し、2番目のパラメーターはインデックスを表します。
使用PyArg_ParseのC ++型の値にPythonオブジェクトを変換する機能。最初のパラメータは、Pythonオブジェクトを表し、2番目のパラメータは、変換されたC ++型のフォーマットを示し、3番目のパラメータは、変換された値に割り当てられた変数(アンパサンドを追加しなければならない)であります
7、終わり
Py_DECREF(pInputRec);
Py_DECREF(pReturn);
Py_DECREF(pParam);
Py_Finalize();
Python呼び出し全体が終了したら、 Py_DECREF(PyObject*)函数释放资源,方便python对象垃圾回收。