over 3 years ago

是說混合編程好像是大陸那邊的用法呢,搜了好多次都是這個名稱.

故事是這樣的,昨天我心血來潮,看看有沒有辦法讓CPython一樣把其他Python檔案Import進來,並且呼叫使用他們的函數,這不難查,很快就查到大量的範例.可是真的把一些範例寫上去後就碰到一些詭異的事情.

不過標題這麼下,看來還是不能只寫遇到的錯誤,先從頭開始講吧:

如何使用

很簡單,只要

#include<python.h>

Mac是

#include<Python/Python.h>

Mac編譯時需要多下-framework Python參數

然後這是我找到的原始範例:

#include <Python/Python.h>
 
int main(){
    Py_Initialize();
    
    PyObject* pModule = PyImport_ImportModule("test2");
    PyObject* pFunc = PyObject_GetAttrString(pModule, "MakeCall");
    //some code
    return 0;
}

路徑設置

這的de很久,我一直Runtime Error在pFunc那行,忍不住去PyObject_Print一下pModule,發現他竟然是<nil>!!??連引入都不成功?

查了一下,發現是需要設置路徑

PySys_SetPath(".");

傳遞函數指標

這個找超久,網路上都沒啥範例,只好自己拼拼湊湊出一個啦.

大概是先建立一個PyMethod,裏面填寫要傳遞的Function Pointer,然後用BuildValue做成Tuple就好了.

以下是完整範例:)

test2.py
def MakeCall(func):
    func()
    return 1
test1.cpp
#include <Python/Python.h>
#include <stdio.h>
int counter = 0;
static PyObject* func(PyObject* a, PyObject* b){
    counter += 1;
    printf("%d\n", counter);
    return Py_None;
}
 
int main(){
    Py_Initialize();
    PySys_SetPath(".");
    
    PyObject* pModule = PyImport_ImportModule("test2");
    PyObject* pFunc = PyObject_GetAttrString(pModule, "MakeCall");
 
    PyMethodDef *callback = new PyMethodDef;
    
    callback->ml_name = "func";
    callback->ml_meth = func;
    callback->ml_flags = 1;
    
    PyObject* pcb = PyCFunction_New(callback, NULL);
    PyObject* pArg = Py_BuildValue("(O)", pcb);
    
    PyObject_CallObject(pFunc, pArg);
     
    printf("call ok, counter = %d\n", counter);
    Py_Finalize();
    return 0;
}
← 因式分解一個有限域的多項式 RPG引擎 - CRPG →
 
comments powered by Disqus