--Pass the value calculated in the C / C ++ source to the python function, and receive the execution result in the C / C ++ source.
--Create an appropriate value in C / C ++ --Print the value with a python function --python functions also return appropriate values --Print the value returned by the python function on the C / C ++ side as well.
(The values of variables used in the program have no meaning)
C/C++
main.cpp
#include <iostream>
#include <vector>
#include <Python.h>
bool isCallable(const char *functionName, PyObject *pythonFunc) {
if (pythonFunc && PyCallable_Check(pythonFunc)) {
return true;
} else {
std::cerr << "Failed to load the function [" << functionName << "]." << std::endl;
return false;
}
}
int main(int argc, char *argv[]) {
const char *pythonFileName = "script"; // The extension (.py) must be removed.
const char *functionName = "test_func"; // This function must be included in the script.
Py_Initialize();
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
PyList_Append(path, PyString_FromString(".")); // Add the current directory to the python path list since the script file is in there.
PyRun_SimpleString("import os, sys\n");
// load the function from the script
PyObject *pythonName = PyString_FromString(pythonFileName);
PyObject *pythonModule = PyImport_Import(pythonName);
Py_DECREF(pythonName);
PyObject *pythonFunc = PyObject_GetAttrString(pythonModule, functionName);
if (!isCallable(functionName, pythonFunc))
exit(-1);
// Create data which will be passed to the python's function.
// Because the numbers of the argument is 2, the python's function must receive 2 arguments (see the script file).
int pythonFuncArgNum = 2;
PyObject *pythonArgs = PyTuple_New(pythonFuncArgNum);
// Create the first argument.
int dataNum = 3;
int channelNum = 2;
int measurementNum = 4;
PyObject *params = PyList_New(3);
PyList_SET_ITEM(params, 0, PyInt_FromLong(dataNum));
PyList_SET_ITEM(params, 1, PyInt_FromLong(channelNum));
PyList_SET_ITEM(params, 2, PyInt_FromLong(measurementNum));
PyTuple_SetItem(pythonArgs, 0, params); // Set the first argument.
// Create the second argument.
PyObject *datas = PyTuple_New(dataNum);
for (int i = 0; i < dataNum; i++) {
PyObject *data = PyTuple_New(channelNum);
PyObject *channel0 = PyList_New(measurementNum);
PyObject *channel1 = PyList_New(measurementNum);
for (int j = 0; j < measurementNum; j++) {
PyList_SET_ITEM(channel0, j, PyFloat_FromDouble(i + j * 2.0));
PyList_SET_ITEM(channel1, j, PyFloat_FromDouble(i * 2.0 + j * 2.0));
}
PyTuple_SetItem(data, 0, channel0);
PyTuple_SetItem(data, 1, channel1);
PyTuple_SetItem(datas, i, data);
}
PyTuple_SetItem(pythonArgs, 1, datas); // Set the second argument.
// Call the python's function and print the returned values.
PyObject *pythonValue = PyObject_CallObject(pythonFunc, pythonArgs);
Py_DECREF(pythonArgs);
std::cout << "Print the results returned from the python function in the C++ source code." << std::endl;
for (int i = 0; i < (int)PyList_Size(pythonValue); i++)
std::cout << i << " , " << PyFloat_AsDouble(PyList_GetItem(pythonValue, i)) << std::endl;
return 0;
}
python
script.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import numpy as np
print 'Scripts written in outside of python functions will be called when this script is loaded by the C++ source code.\n'
# The function must have 2 arguments because the C++ source code gives the function 2 arguments.
def test_func(params, datas):
print 'Start the python function.'
# Copy the parameters.
data_num = params[0]
channel_num = params[1]
measurement_num = params[2]
print 'data_num =', data_num, ', channel_num =', channel_num, ', measurement_num =', measurement_num
# Print the second arguments
for i in range(data_num):
for j in range(measurement_num):
print 'i =', i, ', channel0 =', datas[i][0][j], ', channel1 =', datas[i][1][j]
# Create a dummy result and return it.
values = []
for i in range(data_num):
values.append(i * 3.0)
print 'The python function will return an array (vector) data.\n'
return values
g++ main.cpp -o call_py_func_from_c -L/usr/lib/python2.7 -lpython2.7 -I/usr/include/python2.7
Please change the python version and path accordingly.
Place the C / C ++ and python files in the same directory and run them there (because script.py cannot be found unless the python path is set). In the C / C ++ source code, there is a process to set the current directory to the python path.
Scripts written in outside of python functions will be called when this script is loaded by the C++ source code.
Start the python function.
data_num = 3 , channel_num = 2 , measurement_num = 4
i = 0 , channel0 = 0.0 , channel1 = 0.0
i = 0 , channel0 = 2.0 , channel1 = 2.0
i = 0 , channel0 = 4.0 , channel1 = 4.0
i = 0 , channel0 = 6.0 , channel1 = 6.0
i = 1 , channel0 = 1.0 , channel1 = 2.0
i = 1 , channel0 = 3.0 , channel1 = 4.0
i = 1 , channel0 = 5.0 , channel1 = 6.0
i = 1 , channel0 = 7.0 , channel1 = 8.0
i = 2 , channel0 = 2.0 , channel1 = 4.0
i = 2 , channel0 = 4.0 , channel1 = 6.0
i = 2 , channel0 = 6.0 , channel1 = 8.0
i = 2 , channel0 = 8.0 , channel1 = 10.0
The python function will return an array (vector) data.
Print the results returned from the python function in the C++ source code.
0 , 0
1 , 3
2 , 6
I passed the value calculated in C / C ++ to the python function, and made a program to return the processing performed in the python function to C / C ++.
He says, "I know there are good libraries (deep learning, etc.) in python, but I don't like writing all programs in python" (I can't keep up with new ones ...). So, I basically wrote it in C / C ++ and thought it would be nice to be able to call the python library only when needed.
I think there are already similar pages, but to make sure I don't forget ...
Recommended Posts