最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言中調(diào)用Python腳本的方法詳解

 更新時(shí)間:2025年05月29日 09:56:11   作者:智齒受害者  
在C語(yǔ)言中調(diào)用?Python?腳本的方式有很多,這篇文章主要為大家介紹了人家使用?Python?的?C?API?進(jìn)行調(diào)用?Python?腳本,需要的可以參考一下

在 C 語(yǔ)言中調(diào)用 Python 腳本的方式有很多,在這里使用 Python 的 C API 進(jìn)行調(diào)用 Python 腳本,包括初始化解釋器、執(zhí)行腳本文件(導(dǎo)入模塊和類、創(chuàng)建對(duì)象、調(diào)用對(duì)象方法)以及處理錯(cuò)誤的完整流程。 參考 Python 的 C API 文檔: Python/C API 參考手冊(cè)

示例代碼:python_c_api_demo

環(huán)境準(zhǔn)備

  • 示例使用的是 Python3.9 ,需要安裝 python 3.9 以及 python3-dev
  • 安裝 gcc
  • 執(zhí)行環(huán)境必須有 Python 環(huán)境

簡(jiǎn)單調(diào)用示例

單線程導(dǎo)入模塊以及類,創(chuàng)建對(duì)象,調(diào)用對(duì)象方法。

Python 腳本

example.py

import random
import time


class HelloWorld:
    def __init__(self, name):
        self.name = name

    def say_hi(self):
        print(f'Hi {self.name}')

    def add(self, a, b):
        return a + b

    def random_number(self):
        time.sleep(0.05)
        return random.randint(0, 100)

C 語(yǔ)言代碼

直接在 example.c 中執(zhí)行 Python 腳本。

#include <Python.h>

int main()
{
    // 初始化 Python 解釋器
    Py_Initialize();

    // 添加當(dāng)前目錄到 sys.path(確保能導(dǎo)入 example.py)
    PyObject *pSys = PyImport_ImportModule("sys");
    if (!pSys)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import sys module\n");
        return 1;
    }
    PyObject *pPath = PyObject_GetAttrString(pSys, "path");
    if (!pPath)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get sys.path\n");
        Py_DECREF(pSys);
        return 1;
    }
    int status = PyList_Append(pPath, PyUnicode_FromString("."));
    if (status == -1)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to append path\n");
        Py_DECREF(pPath);
        Py_DECREF(pSys);
        return 1;
    }
    Py_DECREF(pPath);
    Py_DECREF(pSys);

    // 導(dǎo)入 example 模塊
    PyObject *pModule = PyImport_ImportModule("example");
    if (!pModule)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import example module\n");
        Py_Finalize();
        return 1;
    }
    // 導(dǎo)入 HelloWorld 類
    PyObject *pClass = PyObject_GetAttrString(pModule, "HelloWorld");
    if (!pClass)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import HelloWorld class\n");
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 創(chuàng)建對(duì)象
    char name[256] = "XiaoMing";

    PyObject *pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(name));

    PyObject *pInstance = PyObject_CallObject(pClass, pArgs);
    Py_DECREF(pArgs);

    if (pInstance == NULL)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to create instance of HelloWorld\n");
        Py_XDECREF(pClass);
        Py_XDECREF(pModule);
        return 1;
    }

    // 獲取 say_hi 方法
    PyObject *pFuncSayHi = PyObject_GetAttrString(pInstance, "say_hi");
    if (!pFuncSayHi || !PyCallable_Check(pFuncSayHi))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get say_hi function\n");
        Py_DECREF(pInstance);
        Py_DECREF(pClass);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 調(diào)用 say_hi 方法
    PyObject_CallObject(pFuncSayHi, NULL);

    // 獲取 add 函數(shù)
    PyObject *pFuncAdd = PyObject_GetAttrString(pInstance, "add");
    if (!pFuncAdd || !PyCallable_Check(pFuncAdd))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get add function\n");
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        Py_DECREF(pClass);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 構(gòu)造參數(shù)并調(diào)用 add 函數(shù)
    PyObject *pArgsAdd = PyTuple_Pack(2, PyLong_FromLong(3), PyLong_FromLong(4));
    if (!pArgsAdd)
    {
        PyErr_Print();
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        Py_DECREF(pClass);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    PyObject *pResultAdd = PyObject_CallObject(pFuncAdd, pArgsAdd);
    if (!pResultAdd)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to call add function\n");
        Py_DECREF(pArgsAdd);
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        Py_DECREF(pClass);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 處理返回值
    long addResult = PyLong_AsLong(pResultAdd);

    printf("Add Result: %ld\n", addResult);

    // 獲取 random_number 方法
    PyObject *pFuncRandomNumber = PyObject_GetAttrString(pInstance, "random_number");
    if (!pFuncRandomNumber || !PyCallable_Check(pFuncRandomNumber))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get random_number function\n");
        Py_DECREF(pResultAdd);
        Py_DECREF(pArgsAdd);
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        Py_DECREF(pClass);
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    // 調(diào)用 random_number 方法
    PyObject *pRandomNumber = PyObject_CallObject(pFuncRandomNumber, NULL);
    long randomNumber = PyLong_AsLong(pRandomNumber);
    printf("Random Number: %ld\n", randomNumber);

    // 釋放資源
    Py_DECREF(pRandomNumber);
    Py_DECREF(pFuncRandomNumber);
    Py_DECREF(pResultAdd);
    Py_DECREF(pArgsAdd);
    Py_DECREF(pFuncAdd);
    Py_DECREF(pFuncSayHi);
    Py_DECREF(pInstance);
    Py_DECREF(pClass);
    Py_DECREF(pModule);

    // 結(jié)束 Python 解釋器
    Py_Finalize();

    return 0;
}

編譯命令:gcc example.c -I/usr/include/python3.9 -lpython3.9 -o example

多線程調(diào)用示例

當(dāng)在 C 程序中創(chuàng)建多線程調(diào)用 Python API 時(shí),必須注意 GIL 的獲取和釋放,使用 PyGILState_Ensure() 和 PyGILState_Release() 來(lái)獲取和釋放 GIL。 在主線程使用Py_Initialize初始化 Python 解釋器后,主線程會(huì)自動(dòng)持有 GIL,必須顯式釋放 GIL,否則子線程中會(huì)一直阻塞在獲取 GIL

example_threading.c

在主線程中初始化 Python 解釋器,并導(dǎo)入模塊和類,創(chuàng)建多個(gè)線程,每個(gè)線程都創(chuàng)建對(duì)象,并調(diào)用對(duì)象方法。

#include <Python.h>

#define NUM_THREADS 5
#define NUM_ITERATIONS 50

// 線程參數(shù)結(jié)構(gòu)
typedef struct
{
    int thread_id;
    const char *name;
    PyObject *pClass;
} ThreadArgs;

// 生成隨機(jī)字符串的函數(shù)
void generate_random_string(char *buffer, int length, const char *charset)
{
    int charset_len = strlen(charset);
    for (int i = 0; i < length; ++i)
    {
        int index = rand() % charset_len; // 從字符集中隨機(jī)選一個(gè)字符
        buffer[i] = charset[index];
    }
}

// 線程函數(shù)
void *thread_func(void *args)
{
    ThreadArgs *targs = (ThreadArgs *)args;
    int tid = targs->thread_id;
    printf("Thread %d started\n", tid);

    PyGILState_STATE gstate;

    gstate = PyGILState_Ensure();
    PyObject *pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, PyUnicode_FromString(targs->name));
    PyGILState_Release(gstate);

    gstate = PyGILState_Ensure();
    PyObject *pInstance = PyObject_CallObject(targs->pClass, pArgs);
    Py_DECREF(pArgs);
    if (pInstance == NULL)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to create instance of HelloWorld\n");
        PyGILState_Release(gstate);
        return NULL;
    }
    PyGILState_Release(gstate);

    // 獲取 say_hi 方法
    gstate = PyGILState_Ensure();
    PyObject *pFuncSayHi = PyObject_GetAttrString(pInstance, "say_hi");
    if (!pFuncSayHi || !PyCallable_Check(pFuncSayHi))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get say_hi function\n");
        Py_DECREF(pInstance);
        PyGILState_Release(gstate);
        Py_Finalize();
        return NULL;
    }
    // 調(diào)用 say_hi 方法
    PyObject_CallObject(pFuncSayHi, NULL);
    PyGILState_Release(gstate);

    // 獲取 add 函數(shù)
    gstate = PyGILState_Ensure();
    PyObject *pFuncAdd = PyObject_GetAttrString(pInstance, "add");
    if (!pFuncAdd || !PyCallable_Check(pFuncAdd))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get add function\n");
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        PyGILState_Release(gstate);
        Py_Finalize();
        return NULL;
    }
    // 構(gòu)造參數(shù)并調(diào)用 add 函數(shù)
    PyObject *pArgsAdd = PyTuple_Pack(2, PyLong_FromLong(3), PyLong_FromLong(4));
    if (!pArgsAdd)
    {
        PyErr_Print();
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        PyGILState_Release(gstate);
        Py_Finalize();
        return NULL;
    }
    PyObject *pResultAdd = PyObject_CallObject(pFuncAdd, pArgsAdd);
    if (!pResultAdd)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to call add function\n");
        Py_DECREF(pArgsAdd);
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        PyGILState_Release(gstate);
        Py_Finalize();
        return NULL;
    }
    // 處理返回值
    long addResult = PyLong_AsLong(pResultAdd);
    PyGILState_Release(gstate);
    printf("Add Result: %ld\n", addResult);

    // 獲取 random_number 方法
    gstate = PyGILState_Ensure();
    PyObject *pFuncRandomNumber = PyObject_GetAttrString(pInstance, "random_number");
    if (!pFuncRandomNumber || !PyCallable_Check(pFuncRandomNumber))
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get random_number function\n");
        Py_DECREF(pResultAdd);
        Py_DECREF(pArgsAdd);
        Py_DECREF(pFuncAdd);
        Py_DECREF(pFuncSayHi);
        Py_DECREF(pInstance);
        PyGILState_Release(gstate);
        Py_Finalize();
        return NULL;
    }
    PyGILState_Release(gstate);

    srand(time(NULL) + tid);
    // 循環(huán)多次調(diào)用 random_number 方法
    for (int i = 0; i < NUM_ITERATIONS; i++)
    {
        gstate = PyGILState_Ensure();
        PyObject *pRandomNumber = PyObject_CallObject(pFuncRandomNumber, NULL);
        long randomNumber = PyLong_AsLong(pRandomNumber);
        printf("Thread %d, Iteration %d, Random Number: %ld\n", tid, i, randomNumber);
        Py_DECREF(pRandomNumber);
        PyGILState_Release(gstate);
        usleep(10000);
    }

    // 釋放資源
    gstate = PyGILState_Ensure();
    Py_DECREF(pFuncRandomNumber);
    Py_DECREF(pResultAdd);
    Py_DECREF(pArgsAdd);
    Py_DECREF(pFuncAdd);
    Py_DECREF(pFuncSayHi);
    Py_DECREF(pInstance);
    PyGILState_Release(gstate);

    printf("Thread %d end\n", tid);
    return NULL;
}

int main()
{
    // 主線程初始化一次 Python 解釋器
    Py_Initialize();

    // 添加當(dāng)前目錄到 sys.path(確保能導(dǎo)入 example.py)
    PyObject *pSys = PyImport_ImportModule("sys");
    if (!pSys)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import sys module\n");
        return 1;
    }
    PyObject *pPath = PyObject_GetAttrString(pSys, "path");
    if (!pPath)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to get sys.path\n");
        Py_DECREF(pSys);
        return 1;
    }
    int status = PyList_Append(pPath, PyUnicode_FromString("."));
    if (status == -1)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to append path\n");
        Py_DECREF(pPath);
        Py_DECREF(pSys);
        return 1;
    }
    Py_DECREF(pPath);
    Py_DECREF(pSys);

    // 導(dǎo)入 example 模塊
    PyObject *pModule = PyImport_ImportModule("example");
    if (!pModule)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import example module\n");
        Py_Finalize();
        return 1;
    }
    // 導(dǎo)入 HelloWorld 類
    PyObject *pClass = PyObject_GetAttrString(pModule, "HelloWorld");
    if (!pClass)
    {
        PyErr_Print();
        fprintf(stderr, "Failed to import HelloWorld class\n");
        Py_DECREF(pModule);
        Py_Finalize();
        return 1;
    }

    PyEval_SaveThread(); // 釋放 GIL

    srand(time(NULL)); // 初始化隨機(jī)種子

    const char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    // 創(chuàng)建線程
    pthread_t threads[NUM_THREADS];
    ThreadArgs thread_args[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; ++i)
    {
        printf("Create thread %d\n", i);
        char buffer[5]; // 長(zhǎng)度為 5 個(gè)結(jié)束符
        generate_random_string(buffer, 5, charset);

        thread_args[i].thread_id = i;
        thread_args[i].name = buffer;
        thread_args[i].pClass = pClass;

        int rc = pthread_create(&threads[i], NULL, thread_func, &thread_args[i]);
        if (rc)
        {
            fprintf(stderr, "Error creating thread %d\n", i);
            return EXIT_FAILURE;
        }
        // usleep(100000);
    }
    printf("create threads success\n");

    for (int i = 0; i < NUM_THREADS; ++i)
    {
        pthread_join(threads[i], NULL);
    }

    PyGILState_STATE gstate = PyGILState_Ensure();

    Py_DECREF(pClass);
    Py_DECREF(pModule);

    // 結(jié)束 Python 解釋器
    Py_Finalize();
    return 0;
}

編譯命令:gcc example_threading.c -I/usr/include/python3.9 -lpython3.9 -lpthread -o example_threading

跨平臺(tái)編譯

在 x64 上編譯到 arm64 平臺(tái)的可執(zhí)行文件,需要將目標(biāo)設(shè)備上的 python 相關(guān)頭文件和庫(kù)文件復(fù)制到編譯機(jī)上,并使用 aarch64-linux-gnu-gcc 編譯。

編譯命令:aarch64-linux-gnu-gcc example_threading.c -o example_threading_arm64 -I./arm64-python3.12/include/python3.12 -L./arm64-python3.12/lib -lpython3.12 -lpthread -lm -lutil -ldl -Wl,-rpath,.

問(wèn)題

在 Python 腳本中使用 Numpy 時(shí),出現(xiàn)報(bào)錯(cuò):numpy:DLL load failed while importing _multiarray_umath:,如果 Python 庫(kù)中使用了 C 擴(kuò)展,應(yīng)該都會(huì)有這個(gè)問(wèn)題,解決方案:在初始化 python 解釋器前,動(dòng)態(tài)加載 python 的 so 庫(kù)

#include <dlfcn.h>
dlopen("libpython3.9.so", RTLD_LAZY | RTLD_GLOBAL)

以上就是C語(yǔ)言中調(diào)用Python腳本的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言調(diào)用Python腳本的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中new與delete、malloc與free應(yīng)用分析

    C++中new與delete、malloc與free應(yīng)用分析

    這篇文章主要介紹了C++中new與delete、malloc與free應(yīng)用分析,很重要的概念,需要的朋友可以參考下
    2014-08-08
  • C++中的string庫(kù)函數(shù)常見函數(shù)的作用和使用方法

    C++中的string庫(kù)函數(shù)常見函數(shù)的作用和使用方法

    這篇文章主要介紹了C++中的string庫(kù)函數(shù)常見函數(shù)的作用和使用方法,庫(kù)函數(shù)的靈活應(yīng)用是程序員的一大重要技能,本文通過(guò)實(shí)例實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • C++索引越界的解決方法

    C++索引越界的解決方法

    本文主要介紹了C++索引越界的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • QT實(shí)現(xiàn)將兩個(gè)時(shí)間相加的算法[hh:?mm?+?hh:?mm]的示例代碼

    QT實(shí)現(xiàn)將兩個(gè)時(shí)間相加的算法[hh:?mm?+?hh:?mm]的示例代碼

    本文主要介紹了QT實(shí)現(xiàn)將兩個(gè)時(shí)間相加的算法[hh:?mm?+?hh:?mm]的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Qt控件之QDialog使用及技巧小結(jié)

    Qt控件之QDialog使用及技巧小結(jié)

    QDialog是Qt中的一個(gè)類,繼承自QWidget類,用于創(chuàng)建對(duì)話框窗口,可以顯示模態(tài)或非模態(tài)的對(duì)話框,本文就來(lái)介紹一下Qt控件之QDialog使用及技巧小結(jié),感興趣的可以了解一下
    2023-10-10
  • C++編程實(shí)現(xiàn)獲取當(dāng)前可執(zhí)行文件名稱

    C++編程實(shí)現(xiàn)獲取當(dāng)前可執(zhí)行文件名稱

    在C++開發(fā)中,有時(shí)需要獲取當(dāng)前可執(zhí)行文件的名稱用來(lái)處理一些事務(wù),本文總結(jié)了在Windows和Linux平臺(tái)上獲取當(dāng)前可執(zhí)行文件名稱的多種方法,大家可以根據(jù)需要進(jìn)行選擇
    2026-03-03
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄(2)

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄(2)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄的第二部分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Qt中樹形控件Tree Widget的使用方法匯總

    Qt中樹形控件Tree Widget的使用方法匯總

    最近小編在研究Tree Widget樹形控件的相關(guān)知識(shí),這種控件其實(shí)有時(shí)還是很有用處的,我主要利用的是帶有復(fù)選框的樹形控件,下面通過(guò)實(shí)例代碼給大家介紹下Qt中樹形控件Tree Widget的一些使用方法,感興趣的朋友一起學(xué)習(xí)吧
    2021-11-11
  • C++實(shí)現(xiàn)正整數(shù)的四則運(yùn)算表達(dá)式

    C++實(shí)現(xiàn)正整數(shù)的四則運(yùn)算表達(dá)式

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)正整數(shù)的四則運(yùn)算表達(dá)式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • C++實(shí)現(xiàn)LeetCode(148.鏈表排序)

    C++實(shí)現(xiàn)LeetCode(148.鏈表排序)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(148.鏈表排序),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評(píng)論

高雄县| 株洲市| 当涂县| 黄浦区| 建宁县| 奉贤区| 阜新市| 手机| 潢川县| 利辛县| 青海省| 易门县| 富阳市| 南郑县| 杭锦旗| 溧阳市| 杨浦区| 衡东县| 抚松县| 富阳市| 荣成市| 独山县| 大姚县| 屏东县| 襄城县| 新乡市| 苗栗市| 察哈| 乌兰察布市| 盐山县| 凤翔县| 襄汾县| 资中县| 泰安市| 防城港市| 山阴县| 凌云县| 鄂托克旗| 罗平县| 达拉特旗| 双柏县|