In Origin C, there is no way to call Python functions directly. However, if you want to reuse your Python code in Origin C, it is recommended to wrap the Python functions in a DLL first, and then expose the functions in the DLL to Origin C code. In the following sections of this chapter, an example will be shown on how to do this step by step.
Notes: From Origin 2015, we can run python in Origin (support both command line and .py file), and use a PyOrigin module to access Origin from Python. view Python.chm for more details. |
The example shown below is based on the following environment.
The Python functions defined in the following are going to be reused in Origin C.
def SayHello(): print("Welcome to use Python in your Origin C programs!") #actually this string will not show in Origin C return 12345 def Add(a, b): return a + b def Sub(a, b): return a - b def Mult(a, b): return a * b def Div(a, b): return a / b def Mod(a, b): return a % b
python -m py_compile myLib.py
Note: Here the 32-bit DLL will be created, and that will be used in 32-bit version of Origin.
#ifndef _OPYTHON_H_ #define _OPYTHON_H_ #ifdef _OPYTHON_CPP_ #define OP_API __declspec(dllexport) //use in VC #else #define OP_API //use in OC #pragma dll(OPython) //this line is important, when use in OC, Origin will find function body by searching in this DLL. Note:OPythonDLL, is the generated dll, without extension name. #endif OP_API int PY_SayHello(); OP_API float PY_Add(float a, float b); OP_API float PY_Sub(float a, float b); OP_API float PY_Mult(float a, float b); OP_API float PY_Div(float a, float b); OP_API float PY_Mod(float a, float b); #endif //_OPYTHON_H_
#include "stdafx.h" #define _OPYTHON_CPP_ //use this macro to identify whether OPython.h is included in VC(when create the DLL) or OC(when use the DLL) #include "OPython.h" #include <Python.h> class PythonManager { public: PythonManager(); //init python environment ~PythonManager(); //clean python environment }; PythonManager::PythonManager() { Py_Initialize(); } PythonManager::~PythonManager() { Py_Finalize(); } OP_API int PY_SayHello() { PythonManager pm; PyObject* pModule; PyObject* pFunc; //call python function, with no parameters int nRet = 0; pModule = PyImport_ImportModule("myLib"); if ( NULL == pModule ) return nRet; pFunc = PyObject_GetAttrString(pModule, "SayHello"); if ( pFunc ) { PyObject* pRet = NULL; pRet = PyEval_CallObject(pFunc, NULL); PyArg_Parse(pRet, "i", &nRet); } return nRet; } static float _call_float_float(LPCSTR lpcszFunc, float a, float b) { PythonManager pm; PyObject* pModule; PyObject* pFunc; //call python function, with multiple parameters float fRet = 0; pModule = PyImport_ImportModule("myLib"); if ( NULL == pModule ) return fRet; pFunc = PyObject_GetAttrString(pModule, lpcszFunc); if ( pFunc ) { PyObject* pParams = NULL; pParams = PyTuple_New(2); //create tuple to put parameters PyTuple_SetItem(pParams, 0, Py_BuildValue("f", a)); PyTuple_SetItem(pParams, 1, Py_BuildValue("f", b)); PyObject* pRet = NULL; pRet = PyEval_CallObject(pFunc, pParams); PyArg_Parse(pRet, "f", &fRet); } return fRet; } OP_API float PY_Add(float a, float b) { return _call_float_float("Add", a, b); } OP_API float PY_Sub(float a, float b) { return _call_float_float("Sub", a, b); } OP_API float PY_Mult(float a, float b) { return _call_float_float("Mult", a, b); } OP_API float PY_Div(float a, float b) { return _call_float_float("Div", a, b); } OP_API float PY_Mod(float a, float b) { return _call_float_float("Mod", a, b); }
LIBRARY "OPython"
EXPORTS
;Functions to export
PY_SayHello
PY_Add
PY_Sub
PY_Mult
PY_Div
PY_Mod
The following code show how to use the DLL generated above in Origin C.
#include <Origin.h> #include "OPython.h" //remember to include this header. int test_Python() { int nRet = PY_SayHello(); float c = PY_Add(2, 4); float d = PY_Div(2, 3); return 0; }
test_Python;
The example shown in this page is only to create a simple DLL that can reuse the functions written in Python. If to process a large amount of data in Python, and transfer the data between Origin and Python, a buffer will be recommended. With buffer, when transfer data from Origin's Column, the vector, which contains data, can be passed from Origin C to a DLL function, which receive a pointer (maybe double *pBuffer) as parameter. And any change based on this buffer will take effect immediately on the vector in Origin C. In \Samples\Python folder of your Origin software, you can see code example( CCallPython.cpp , CCallPython.py , and python.h ) to transfer data buffer by two OC API:
OPYTHON_API OIP OPy_GetItemsFromList(int nType, void* pyObj, void* pBuffer); OPYTHON_API void* OPy_SetItemsToList(int nType, void* pBuffer, OIP* pnDims, int nDims);