程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> C/Python 之間的調用關系

C/Python 之間的調用關系

編輯:關於PHP編程

C/Python 之間的調用關系


由於python有很多功能強大的開源庫,c可以借用其中方法,完成更多的功能。

因此C調用python的方法尤其重要。

方法/步驟

  1. ubuntu 14.04 linux c

    gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

    Python 2.7.6

  2. file 1 [python file]: math_test.py


    def add_func(a,b):

    return a+b


    def sub_func(a,b):

    return (a-b)


    file 2 [c source file]: c_call_python.c


    #include

    #include

    #include

    #include "python2.7/Python.h"


    int main(int argc, char** argv)

    {

    int arg0 = 0,arg1 = 0;

    if(argc == 3){

    arg0 = atoi(argv[1]);

    arg1 = atoi(argv[2]);

    }else{

    printf("please input 2 args!!\n");

    return -1;

    }


    Py_Initialize();

    if ( !Py_IsInitialized())

    return -1;

    PyRun_SimpleString("import sys");

    PyRun_SimpleString("sys.path.append('./')");

    PyObject *pModule;

    PyObject *pFunction;

    PyObject *pArgs;

    PyObject *pRetValue;


    pModule = PyImport_ImportModule("math_test");

    if(!pModule){

    printf("import python failed!!\n");

    return -1;

    }


    pFunction = PyObject_GetAttrString(pModule, "add_func");

    if(!pFunction){

    printf("get python function failed!!!\n");

    return -1;

    }



    pArgs = PyTuple_New(2);

    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", arg0));

    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", arg1));


    pRetValue = PyObject_CallObject(pFunction, pArgs);

    printf("%d + %d = %ld\n",arg0,arg1,PyInt_AsLong(pRetValue));


    Py_DECREF(pModule);

    Py_DECREF(pFunction);

    Py_DECREF(pArgs);

    Py_DECREF(pRetValue);


    Py_Finalize();

    return 0;

    }

  3. 3

    root@linux:~/code# gcc -o c_call_python c_call_python.c -lpython2.7

    root@linux:~/code# ./c_call_python 12 15

    12 + 15 = 27

    Python 擴展中的Py_BuildValue()函數

    Py_BuildValue()函數的作用和PyArg_ParseTuple()的作用相反,它是將C類型的數據結構轉換成Python對象,該函數的原型: PyObject *Py_BuildValue(char *format, ...) 該函數可以和PyArg_ParseTuple()函數一樣識別一系列的格式串,但是輸入參數只能是值,而不能是指針。它返回一個Python對象。 和PyArg_ParseTuple()不同的一點是PyArg_ParseTuple()函數它的第一個參數為元組,Py_BuildValue()則不一定會生成一個元組。它生成一個元組僅僅當格式串包含兩個或者多個格式單元,如果格式串為空,返回NONE。 在下面的描述中,括號中的項是格式單元返回的Python對象類型,方括號中的項為傳遞的C的值的類型。 "s" (string) [char *] :將C字符串轉換成Python對象,如果C字符串為空,返回NONE。 "s#" (string) [char *, int] :將C字符串和它的長度轉換成Python對象,如果C字符串為空指針,長度忽略,返回NONE。 "z" (string orNone) [char *] :作用同"s"。 "z#" (string orNone) [char *, int] :作用同"s#"。 "i" (integer) [int] :將一個C類型的int轉換成Python int對象。 "b" (integer) [char] :作用同"i"。 "h" (integer) [short int] :作用同"i"。 "l" (integer) [long int] :將C類型的long轉換成Pyhon中的int對象。 "c" (string of length 1) [char] :將C類型的char轉換成長度為1的Python字符串對象。 "d" (float) [double] :將C類型的double轉換成python中的浮點型對象。 "f" (float) [float] :作用同"d"。 "O&" (object) [converter,anything] :將任何數據類型通過轉換函數轉換成Python對象,這些數據作為轉換函數的參數被調用並且返回一個新的Python對象,如果發生錯誤返回NULL。 "(items)" (tuple) [matching-items] :將一系列的C值轉換成Python元組。 "[items]" (list) [matching-items] :將一系列的C值轉換成Python列表。 "{items}" (dictionary) [matching-items] :將一系類的C值轉換成Python的字典,每一對連續的C值將轉換成一個鍵值對。
    例如: Py_BuildValue("") None Py_BuildValue("i", 123) 123 Py_BuildValue("iii", 123, 456, 789) (123, 456, 789) Py_BuildValue("s", "hello") 'hello' Py_BuildValue("ss", "hello", "world") ('hello', 'world') Py_BuildValue("s#", "hello", 4) 'hell' Py_BuildValue("()") () Py_BuildValue("(i)", 123) (123,) Py_BuildValue("(ii)", 123, 456) (123, 456) Py_BuildValue("(i,i)", 123, 456) (123, 456) Py_BuildValue("[i,i]", 123, 456) [123, 456] Py_BuildValue("{s:i,s:i}","abc", 123, "def", 456) {'abc': 123, 'def': 456} Py_BuildValue("((ii)(ii)) (ii)",1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))

    深入淺析 C++ 調用 Python 模塊





    Python 提供了 C++ 庫,使得開發者能很方便地從 C++ 程序中調用 Python 模塊。接下來通過本文給大家介紹 C++ 調用 Python 模塊的相關知識,需要的朋友參考下吧

    一般開發過游戲的都知道Lua和C++可以很好的結合在一起,取長補短,把Lua腳本當成類似動態鏈接庫來使用,很好的利用了腳本開發的靈活性。而作為一門流行的通用型腳本語言Python,也是可以做到的。在一個C++應用程序中,我們可以用一組插件來實現一些具有統一接口的功能,一般插件都是使用動態鏈接庫實現,如果插件的變化比較頻繁,我們可以使用Python來代替動態鏈接庫形式的插件(堪稱文本形式的動態鏈接庫),這樣可以方便地根據需求的變化改寫腳本代碼,而不是必須重新編譯鏈接二進制的動態鏈接庫。靈活性大大的提高了。

    作為一種膠水語言,Python 能夠很容易地調用 C 、 C++ 等語言,也能夠通過其他語言調用 Python 的模塊。

    Python 提供了 C++ 庫,使得開發者能很方便地從 C++ 程序中調用 Python 模塊。

    具體的文檔參考官方指南:

    Embedding Python in Another Application

    調用方法

    1 鏈接到 Python 調用庫

    Python 安裝目錄下已經包含頭文件( include 目錄)和庫文件 ( Windows 下為 python27.lib)。

    使用之前需要鏈接到此庫。

    2 直接調用 Python 語句

    #include "python/Python.h"int main(){Py_Initialize(); ## 初始化PyRun_SimpleString("print 'hello'");Py_Finalize(); ## 釋放資源}

    3 加載 Python 模塊並調用函數

    ~/test 目錄下含有 test.py :

    def test_add(a, b):print 'add ', a, ' and ', breturn a+b

    則可以通過以下代碼調用 test_add 函數 :

    #include "python/Python.h"#include using namespace std;int main(){Py_Initialize(); // 初始化// 將Python工作路徑切換到待調用模塊所在目錄,一定要保證路徑名的正確性string path = "~/test";string chdir_cmd = string("sys.path.append(\"") + path + "\")";const char* cstr_cmd = chdir_cmd.c_str();PyRun_SimpleString("import sys");PyRun_SimpleString(cstr_cmd);// 加載模塊PyObject* moduleName = PyString_FromString("test"); //模塊名,不是文件名PyObject* pModule = PyImport_Import(moduleName);if (!pModule) // 加載模塊失敗{cout << "[ERROR] Python get module failed." << endl;return 0;}cout << "[INFO] Python get module succeed." << endl;// 加載函數PyObject* pv = PyObject_GetAttrString(pModule, "test_add");if (!pv || !PyCallable_Check(pv)) // 驗證是否加載成功{cout << "[ERROR] Can't find funftion (test_add)" << endl;return 0;}cout << "[INFO] Get function (test_add) succeed." << endl;// 設置參數PyObject* args = PyTuple_New(2); // 2個參數PyObject* arg1 = PyInt_FromLong(4); // 參數一設為4PyObject* arg2 = PyInt_FromLong(3); // 參數二設為3PyTuple_SetItem(args, 0, arg1);PyTuple_SetItem(args, 1, arg2);// 調用函數PyObject* pRet = PyObject_CallObject(pv, args);// 獲取參數if (pRet) // 驗證是否調用成功{long result = PyInt_AsLong(pRet);cout << "result:" << result;}Py_Finalize(); ## 釋放資源return 0;}

    參數傳遞

    1 C++ 向 Python 傳遞參數

    Python 的參數實際上是元組,因此傳參實際上就是構造一個合適的元組。

    常用的有兩種方法:

    使用 PyTuple_New 創建元組, PyTuple_SetItem 設置元組值

    PyObject* args = PyTuple_New(3);PyObject* arg1 = Py_BuildValue("i", 100); // 整數參數PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮點數參數PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串參數PyTuple_SetItem(args, 0, arg1);PyTuple_SetItem(args, 1, arg2);PyTuple_SetItem(args, 2, arg3);

    直接使用Py_BuildValue構造元組

    PyObject* args = Py_BuildValue("ifs", 100, 3.14, "hello");PyObject* args = Py_BuildValue("()"); // 無參函數

    i, s, f之類的格式字符串可以參考 格式字符串

    2 轉換 Python 返回值

    調用 Python 得到的都是PyObject對象,因此需要使用 Python 提供的庫裡面的一些函數將返回值轉換為 C++ , 例如 PyInt_AsLong,PyFloat_AsDouble, PyString_AsString 等。

    還可以使用 PyArg_ParseTuple 函數來將返回值作為元組解析。

    PyArg_Parse 也是一個使用很方便的轉換函數。

    PyArg_ParseTuple 和 PyArg_Parse 都使用 格式字符串

    注意事項

    需要將 Python 的工作目錄切換到模塊所在路徑 按照模塊名加載而不是文件名 模塊加載或者函數加載需要驗證是否成功,否則可能會引起堆棧錯誤導致程序崩潰 需要使用 Py_DECREF(PyObject*) 來解除對象的引用(以便Python垃圾回收)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved