外部DLLからPythonにアクセスする

Origin Cでは、直接Pythonを呼び出す方法はありません。Origin C内でPythonコードを再利用したい場合、まずDLLにPython関数をラップした後、関数をDLLでOrigin Cコードに公開することをお勧めします。この章の以下の節では、手順を追ってこれを説明するサンプルを示します。

Notes: Origin 2015からpythonをOriginで実行でき(コマンドラインと.pyファイルの両方をサポート)、PyOrigin モジュールを使用してPythonからOriginにアクセス可能です。詳細は、Python.chm を確認してください。

実行環境

このサンプルは以下の環境で行ったものです。

  1. Windows 7
  2. Python 3.3.5 (Python の設定は完了していることを仮定)
  3. Visual Studio 2012

Pythonファイル

以下で定義されるPython関数を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
  1. 最初にPythonのインストールディレクトリを開き、このディレクトリ下にPythonファイル"myLib.py"を作成します。メモ帳等のテキストエディタを使用して新しく作成したファイルを開いて、このファイルに上述のPythonコードを貼り付け、保存します。
  2. コマンドプロンプト (cmd.exe) を実行し、現在のパスをPythonがインストールされているディレクトリに切り替えます。
  3. 以下のコマンドを実行して、作成したPythonファイルをコンパイルします。
    python -m py_compile myLib.py
                    
    
    成功したら、デフォルトでpycファイルが<Pythonインストールディレクトリ>/__pycache__/ フォルダ下に作成されます。

組み込みDLL

  1. Visual Studio 2012を開始し、OPythonという名前の新しいWin32プロジェクトを作成します。

    PythonDLL 1.png

  2. OKをクリックし、アプリケーションの種類をDLLにして完了をクリックしてプロジェクトを作成します。

    PythonDLL 2.png

  3. ソリューション構成Releaseに設定します。プロジェクトを右クリックして、プロパティを選択し、プロパティダイアログを開きます。

    Note: 32-bit DLLを作成したので、32-bit版のOriginで使用できます。

  4. プロパティダイアログで、左パネルから構成プロパティ:VC++ ディレクトリを選択し、右パネルでインクルードディレクトリライブラリ ディレクトリそれぞれにPythonヘッダファイルパスとライブラリパスを追加します。

    PythonDLL 3.png

  5. 左パネルから構成プロパティ:リンカー:入力を選択し、右パネルで追加の依存ファイルにPythonライブラリpython33.libを追加します。他の設定はそのままにして、OKをクリックします。

    PythonDLL 4.png

  6. プロジェクトにヘッダファイルOPython.hを追加して以下のコードを貼り付けます。
    #ifndef _OPYTHON_H_
    #define  _OPYTHON_H_
     
    #ifdef   _OPYTHON_CPP_
            #define    OP_API  __declspec(dllexport) //use in VC
    #else
            #define    OP_API                                                  //OCで使用
            #pragma dll(OPython) //この行は重要です。OCで使用するとき、Originは、このDLLを検索することで関数本体を探します。Note: dllで生成されるOPythonDLLは拡張名なしです。
    #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_
            
    
  7. プロジェクトを作成すると自動で生成されるOPython.cppを開きます(ない場合作成します)。元のコードを以下のコードで置き換えます。
    #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);
    }
    
  8. モジュール定義ファイルOPython.defをプロジェクトに追加し、元のコードを以下のコードに置き換えます。
    LIBRARY "OPython"
    EXPORTS
                    ;Functions to export
                    PY_SayHello
                    PY_Add
                    PY_Sub
                    PY_Mult
                    PY_Div
                    PY_Mod
    
  9. OPython.dllというDLLを作成するためにソリューションをビルドします。

DLLを使用

以下のコードは、上で作成したDLLをOrigin Cで使用する方法を示します。

  1. 作成したDLL(OPython.dll)をコピーして、Originのインストールディレクトリに貼り付けます。
  2. 作成したヘッダファイル(OPython.h)を次のフォルダにコピーします:<ユーザファイルフォルダ>/OriginC/
  3. 32bit版Originを起動し、コードビルダを開きます。新しいCファイルを作成し、以下のコードで置き換えます。
    #include <Origin.h>
    #include "OPython.h" //このヘッダファイルをインクルードすること
    int test_Python()
    {
            int nRet = PY_SayHello();
            float c = PY_Add(2, 4);
            
            float d = PY_Div(2, 3);
            return 0;
    }
    
  4. コードビルダで上のコードをコンパイルし、以下の行をLabTalkコンソール(コードビルダのメニューから表示:LabTalk コンソールを選択)で実行します。
    test_Python;
    

備考

このページのサンプルでは、Pythonで記述された関数を再利用するシンプルなDLLを作成します。大量データをPython で処理してOriginとPython間でデータを交換したい場合、バッファが推奨されます。Originの列からデータを渡すとき、データを持つベクターを、OriginCからパラメータをポインタ(double* pBuffer) で受けるDLL関数に渡します。このバッファに基づく変更はすべて即座にOrigin C内のベクターに反映されます。