C/C++工程中的Plugin機制設計與Python實現

C/C++工程中的Plugin機制設計與Python實現

1. Plugin機制設計概述

在C/C++工程中實現Plugin機制通常需要以下幾個關鍵組件:

  1. Plugin接口定義:定義統一的接口規范
  2. 動態加載機制:運行時加載動態庫
  3. 注冊機制:Plugin向主程序注冊自己
  4. 通信機制:主程序與Plugin之間的數據交換

2. C/C++端的Plugin系統實現

2.1 定義Plugin接口

首先,我們定義一個簡單的Plugin接口頭文件:

// plugin_interface.h
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H#ifdef __cplusplus
extern "C" {
#endif// 定義插件類型
typedef enum {PLUGIN_TYPE_UNKNOWN = 0,PLUGIN_TYPE_FILTER,PLUGIN_TYPE_TRANSFORM,PLUGIN_TYPE_ANALYZER
} PluginType;// 插件基本信息結構
typedef struct {const char* name;const char* version;PluginType type;
} PluginInfo;// 插件操作接口
typedef struct {// 獲取插件信息PluginInfo (*get_info)();// 初始化插件int (*initialize)(void* config);// 執行插件功能void* (*execute)(void* input);// 清理插件void (*cleanup)();
} PluginAPI;// 插件注冊函數原型
typedef void (*RegisterPluginFunc)(PluginAPI*);#ifdef __cplusplus
}
#endif#endif // PLUGIN_INTERFACE_H

2.2 主程序實現Plugin加載

// main.cpp
#include <iostream>
#include <vector>
#include <string>
#include <dlfcn.h> // Unix動態加載庫
#include "plugin_interface.h"class PluginManager {
public:~PluginManager() {for (auto handle : plugin_handles) {dlclose(handle);}}void load_plugin(const std::string& path) {void* handle = dlopen(path.c_str(), RTLD_LAZY);if (!handle) {std::cerr << "Cannot load plugin: " << dlerror() << std::endl;return;}auto register_func = (RegisterPluginFunc)dlsym(handle, "register_plugin");if (!register_func) {std::cerr << "Cannot find register_plugin function: " << dlerror() << std::endl;dlclose(handle);return;}PluginAPI* api = new PluginAPI();register_func(api);plugins.push_back(api);plugin_handles.push_back(handle);PluginInfo info = api->get_info();std::cout << "Loaded plugin: " << info.name << " (v" << info.version << ")" << std::endl;}void execute_all(void* input) {for (auto plugin : plugins) {void* result = plugin->execute(input);// 處理結果...}}private:std::vector<PluginAPI*> plugins;std::vector<void*> plugin_handles;
};int main() {PluginManager manager;// 加載插件manager.load_plugin("./plugins/libfilter_plugin.so");manager.load_plugin("./plugins/libtransform_plugin.so");// 執行插件std::string input = "test data";manager.execute_all((void*)input.c_str());return 0;
}

3. Python實現Plugin功能

3.1 使用ctypes實現Python Plugin

我們可以使用Python的ctypes模塊來實現與C接口兼容的Plugin:

# filter_plugin.py
import ctypes
from ctypes import c_char_p, c_void_p, CFUNCTYPE, Structure, POINTER# 定義C兼容的結構體和枚舉
class PluginInfo(Structure):_fields_ = [("name", c_char_p),("version", c_char_p),("type", ctypes.c_int)]class PluginAPI(Structure):_fields_ = [("get_info", c_void_p),("initialize", c_void_p),("execute", c_void_p),("cleanup", c_void_p)]# 定義插件函數
def get_info():info = PluginInfo()info.name = b"PythonFilterPlugin"info.version = b"1.0"info.type = 1  # PLUGIN_TYPE_FILTERreturn infodef initialize(config):print("Python plugin initialized with config:", config)return 0def execute(input_data):input_str = ctypes.cast(input_data, c_char_p).value.decode('utf-8')print(f"Python plugin processing: {input_str}")output = f"Processed by Python: {input_str.upper()}"return ctypes.c_char_p(output.encode('utf-8'))def cleanup():print("Python plugin cleanup")# 創建函數指針
GET_INFO_FUNC = CFUNCTYPE(PluginInfo)(get_info)
INITIALIZE_FUNC = CFUNCTYPE(ctypes.c_int, c_void_p)(initialize)
EXECUTE_FUNC = CFUNCTYPE(c_void_p, c_void_p)(execute)
CLEANUP_FUNC = CFUNCTYPE(None)(cleanup)# 注冊函數
def register_plugin(api_ptr):api = ctypes.cast(api_ptr, POINTER(PluginAPI)).contentsapi.get_info = ctypes.cast(GET_INFO_FUNC, c_void_p)api.initialize = ctypes.cast(INITIALIZE_FUNC, c_void_p)api.execute = ctypes.cast(EXECUTE_FUNC, c_void_p)api.cleanup = ctypes.cast(CLEANUP_FUNC, c_void_p)

3.2 使用Cython包裝Python Plugin

為了更好集成,可以使用Cython創建真正的動態庫:

# pyplugin_wrapper.pyx
cimport cpythonfrom libc.stdlib cimport malloc, free
from libc.string cimport strdupfrom filter_plugin import register_plugin as py_register_plugincdef extern from "plugin_interface.h":ctypedef struct PluginInfo:const char* nameconst char* versionint typectypedef struct PluginAPI:PluginInfo (*get_info)()int (*initialize)(void* config)void* (*execute)(void* input)void (*cleanup)()cdef PluginInfo get_info_wrapper():from filter_plugin import get_info as py_get_infopy_info = py_get_info()cdef PluginInfo infoinfo.name = strdup(py_info.name)info.version = strdup(py_info.version)info.type = py_info.typereturn infocdef int initialize_wrapper(void* config):from filter_plugin import initialize as py_initializereturn py_initialize(config)cdef void* execute_wrapper(void* input):from filter_plugin import execute as py_executereturn py_execute(input)cdef void cleanup_wrapper():from filter_plugin import cleanup as py_cleanuppy_cleanup()cdef PluginAPI* create_api():cdef PluginAPI* api = <PluginAPI*>malloc(sizeof(PluginAPI))api.get_info = get_info_wrapperapi.initialize = initialize_wrapperapi.execute = execute_wrapperapi.cleanup = cleanup_wrapperreturn apicdef void register_plugin(PluginAPI* api):py_register_plugin(api)

然后創建setup.py編譯為動態庫:

# setup.py
from distutils.core import setup
from Cython.Build import cythonizesetup(name='pyplugin',ext_modules=cythonize("pyplugin_wrapper.pyx"),
)

編譯命令:

python setup.py build_ext --inplace

4. 完整工作流程

  1. C++主程序

    • 定義Plugin接口
    • 實現動態加載機制
    • 提供Plugin注冊和管理功能
  2. Python Plugin

    • 使用ctypes或Cython實現兼容的接口
    • 實現具體的業務邏輯
    • 編譯為動態庫(.so或.dll)
  3. 運行時

    • 主程序加載Python編譯的動態庫
    • Python Plugin注冊到主程序
    • 主程序調用Python實現的功能

5. 高級主題

  1. 多語言類型轉換

    • 使用Protocol Buffers或JSON進行復雜數據交換
    • 實現類型轉換層處理C/C++與Python類型差異
  2. 線程安全

    • 處理GIL(Global Interpreter Lock)問題
    • 確保多線程環境下安全調用Python代碼
  3. 性能優化

    • 減少C/Python邊界 crossing
    • 批量處理數據
  4. 錯誤處理

    • 捕獲Python異常并轉換為C錯誤碼
    • 實現安全的資源清理

這種設計模式在現代軟件中很常見,如Blender、GIMP等開源軟件都采用了類似的架構來實現插件系統。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79721.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79721.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79721.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

node-sass安裝失敗解決方案

1、python環境問題 Error: Cant find Python executable "python", you can set the PYTHON env variable. 提示找不到python2.7版本&#xff0c; 方法一&#xff1a;可安裝一個python2.7或引用其他已安裝的python2.7 通過設置環境變量可以解決&#xff1b; 方法二&…

Netty高并發物聯網通信服務器實戰:協議優化與性能調優指南

目錄 1.總體設計 2.自定義協議設計(簡單版) 3.消息類型(1字節) 4.項目結構 5.核心功能代碼 (1)pom.xml(Maven依賴) (2)IotServer.java(服務器啟動器) (3)IotServerInitializer.java(Pipeline初始化) (4)DeviceChannelManager.java(設備連接管理器)…

多模態大語言模型arxiv論文略讀(六十)

Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文標題&#xff1a;Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文作者&#xff1a;Timin Gao, Peixian Chen, Mengdan Zhang, Chaoyou Fu, Yunhang Shen, Yan Zhang, Shengchuan Zhang, Xi…

面試常問系列(一)-神經網絡參數初始化-之自注意力機制為什么除以根號d而不是2*根號d或者3*根號d

首先先羅列幾個參考文章&#xff0c;大家之后可以去看看&#xff0c;加深理解&#xff1a; 面試常問系列(一)-神經網絡參數初始化面試常問系列(一)-神經網絡參數初始化之自注意力機制_注意力機制的參數初始化怎么做-CSDN博客面試常問系列(一)-神經網絡參數初始化-之-softmax-C…

第5篇:EggJS中間件開發與實戰應用

在Web開發中&#xff0c;中間件&#xff08;Middleware&#xff09;是處理HTTP請求和響應的核心機制之一。EggJS基于Koa的洋蔥模型實現了高效的中間件機制&#xff0c;本文將深入探討中間件的執行原理、開發實踐以及常見問題解決方案。 一、中間件執行機制與洋蔥模型 1. 洋蔥模…

樹狀結構轉換工具類

項目中使用了很多樹狀結構&#xff0c;為了方便使用開發一個通用的工具類。 使用工具類的時候寫一個類基礎BaseNode&#xff0c;如果有個性化字段添加到類里面&#xff0c;然后就可以套用工具類。 工具類會將id和pid做關聯返回一個樹狀結構的集合。 使用了hutool的工具包判空…

【Python】--裝飾器

裝飾器&#xff08;Decorator&#xff09;本質上是一個返回函數的函數 主要作用是&#xff1a;在不修改原函數代碼的前提下&#xff0c;給函數增加額外的功能 比如&#xff1a;增加業務&#xff0c;日志記錄、權限驗證、執行時間統計、緩存等場景 my_decorator def func():pas…

AI教你學VUE——Gemini版

前端開發學習路線圖 (針對編程新手&#xff0c;主攻 Vue 框架) 總原則&#xff1a;先夯實基礎&#xff0c;再深入框架。 想象一下建房子&#xff0c;地基不牢&#xff0c;上面的高樓&#xff08;框架&#xff09;是蓋不起來的。HTML、CSS、JavaScript 就是前端的地基。 階段一…

神經網絡中之多類別分類:從基礎到高級應用

神經網絡中之多類別分類&#xff1a;從基礎到高級應用 摘要 在機器學習領域&#xff0c;多類別分類是解決復雜問題的關鍵技術之一。本文深入探討了神經網絡在多類別分類中的應用&#xff0c;從基礎的二元分類擴展到一對多和一對一分類方法。我們詳細介紹了 softmax 函數的原理…

Go Web 后臺管理系統項目詳解

Go Web 后臺管理系統項目詳解 一、背景介紹 這是一個基于 Go 語言開發的 Web 后臺管理系統&#xff0c;為筆者學習期間練手之作&#xff0c;較為粗糙 二、技術架構 后端 語言 &#xff1a;采用 Go 語言&#xff08;Golang&#xff09;編寫&#xff0c;因其簡潔高效、并發能…

【Python系列】Python 中的 HTTP 請求處理

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

OS7.【Linux】基本指令入門(6)

目錄 1.zip和unzip 配置指令 使用 兩個名詞:打包和壓縮 打包 壓縮 Linux下的操作演示 壓縮和解壓縮文件 壓縮和解壓縮目錄 -d選項 2.tar Linux下的打包和壓縮方案簡介 czf選項 xzf選項 -C選項 tzf選項 3.bc 4.uname 不帶選項的uname -a選項 -r選項 -v選項…

windows系統 壓力測試技術

一、CPU壓測模擬 工具&#xff1a;CpuStres v2.0 官網&#xff1a;https://learn.microsoft.com/en-us/sysinternals/downloads/cpustres 功能&#xff1a;是一個工具類&#xff0c;用來模擬在一個進程中啟動最多64個線程&#xff0c;且可以獨立控制任何一個線程的啟動/暫停、…

64.搜索二維矩陣

給你一個滿足下述兩條屬性的 m x n 整數矩陣&#xff1a; 每行中的整數從左到右按非嚴格遞增順序排列。每行的第一個整數大于前一行的最后一個整數。 給你一個整數 target &#xff0c;如果 target 在矩陣中&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 示…

在 PyTorch 中借助 GloVe 詞嵌入完成情感分析

一. Glove 詞嵌入原理 GloVe是一種學習詞嵌入的方法&#xff0c;它希望擬合給定上下文單詞i時單詞j出現的次數。使用的誤差函數為&#xff1a; 其中N是詞匯表大小&#xff0c;是線性層參數&#xff0c; 是詞嵌入。f(x)是權重項&#xff0c;用于平衡不同頻率的單詞對誤差的影響…

kotlin中 熱流 vs 冷流 的本質區別

&#x1f525; 冷流&#xff08;Cold Flow&#xff09; vs 熱流&#xff08;Hot Flow&#xff09;區別 特性冷流&#xff08;Cold Flow&#xff09;熱流&#xff08;Hot Flow&#xff09;數據生產時機每次 collect 才開始執行啟動時就開始生產、始終運行生命周期與 collect 者…

精益數據分析(44/126):深度解析媒體網站商業模式的關鍵要點

精益數據分析&#xff08;44/126&#xff09;&#xff1a;深度解析媒體網站商業模式的關鍵要點 在創業與數據分析的探索道路上&#xff0c;我們不斷挖掘不同商業模式的核心要素&#xff0c;今天將深入剖析媒體網站商業模式。希望通過對《精益數據分析》相關內容的解讀&#xf…

Android學習總結之Java和kotlin區別

一、空安全機制 真題 1&#xff1a;Kotlin 如何解決 Java 的 NullPointerException&#xff1f;對比兩者在空安全上的設計差異 解析&#xff1a; 核心考點&#xff1a;Kotlin 可空類型系統&#xff08;?&#xff09;、安全操作符&#xff08;?./?:&#xff09;、非空斷言&…

[Survey]Remote Sensing Temporal Vision-Language Models: A Comprehensive Survey

BaseInfo TitleRemote Sensing Temporal Vision-Language Models: A Comprehensive SurveyAdresshttps://arxiv.org/abs/2412.02573Journal/Time2024 arxivAuthor北航 上海AI LabCodehttps://github.com/Chen-Yang-Liu/Awesome-RS-Temporal-VLM 1. Introduction 傳統遙感局限…

jmeter讀取CSV文件中文亂碼的解決方案

原因分析? CSV文件出現中文亂碼通常是因為文件編碼與JMeter讀取編碼不一致。常見場景&#xff1a; 文件保存為GBK/GB2312編碼&#xff0c;但JMeter以UTF-8讀取。文件包含BOM頭&#xff08;如Windows記事本保存的UTF-8&#xff09;&#xff0c;但JMeter未正確處理。腳本讀取文…