亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

shiboken綁定C++供python使用

系統 1519 0

C++類函數封裝給python調用,大致分為三個部分,第一部分是把我們的C++類函數等封裝成一個dll,即動態庫。第二部分是生成一個綁定代碼,就是用shiboken2根據我們需要封裝暴露的文件,生成pythonC++代碼。然后第三部分,就是根據第一和第二部分生成的庫和代碼,進一步封裝成py庫。然后python文件直接可以調用該庫。具體代碼如下,源碼用的是python的官方源碼。主要講解每個部分的使用。

源碼:
------------------icecream.cpp------------------------------------
#include "icecream.h"

Icecream::Icecream(const std::string &flavor) : m_flavor(flavor) {}

Icecream::~Icecream() {}

const std::string Icecream::getFlavor()
{
? ? return m_flavor;
}

Icecream *Icecream::clone()
{
? ? return new Icecream(*this);
}
-------------------------------------------icecream.h------------------------------------------------------

#ifndef ICECREAM_H
#define ICECREAM_H

#include

#include "macros.h"

class BINDINGS_API Icecream
{
public:
? ? Icecream(const std::string &flavor);
? ? virtual Icecream *clone();
? ? virtual ~Icecream();
? ? virtual const std::string getFlavor();

private:
? ? std::string m_flavor;
};


#endif // ICECREAM_H
--------------------------------------------truck.cpp------------------------------------------------------

#include
#include

#include "truck.h"

Truck::Truck(bool leaveOnDestruction) : m_leaveOnDestruction(leaveOnDestruction) {}

Truck::Truck(const Truck &other)
{
? ? for (size_t i = 0; i < other.m_flavors.size(); ++i) {
? ? ? ? addIcecreamFlavor(other.m_flavors[i]->clone());
? ? }
}

Truck &Truck::operator=(const Truck &other)
{
? ? if (this != &other) {
? ? ? ? clearFlavors();
? ? ? ? for (size_t i = 0; i < other.m_flavors.size(); ++i) {
? ? ? ? ? ? addIcecreamFlavor(other.m_flavors[i]->clone());
? ? ? ? }
? ? }
? ? return *this;
}

Truck::~Truck()
{
? ? if (m_leaveOnDestruction)
? ? ? ? leave();
? ? clearFlavors();
}

void Truck::addIcecreamFlavor(Icecream *icecream)
{
? ? m_flavors.push_back(icecream);
}

void Truck::printAvailableFlavors() const
{
? ? std::cout << "It sells the following flavors: \n";
? ? for (size_t i = 0; i < m_flavors.size(); ++ i) {
? ? ? ? std::cout << " ?* " ?<< m_flavors[i]->getFlavor() << '\n';
? ? }
? ? std::cout << '\n';
}

void Truck::arrive() const
{
? ? std::cout << m_arrivalMessage;
}

void Truck::leave() const
{
? ? std::cout << "The truck left the neighborhood.\n";
}

void Truck::setLeaveOnDestruction(bool value)
{
? ? m_leaveOnDestruction = value;
}

void Truck::setArrivalMessage(const std::string &message)
{
? ? m_arrivalMessage = message;
}

bool Truck::deliver() const
{
? ? std::random_device rd;
? ? std::mt19937 mt(rd());
? ? std::uniform_int_distribution dist(1, 2);

? ? std::cout << "The truck started delivering icecream to all the kids in the neighborhood.\n";
? ? bool result = false;

? ? if (dist(mt) == 2)
? ? ? ? result = true;

? ? return result;
}

void Truck::clearFlavors()
{
? ? for (size_t i = 0; i < m_flavors.size(); ++i) {
? ? ? ? delete m_flavors[i];
? ? }
? ? m_flavors.clear();
}

----------------------------------------------truck.h----------------------------------------------------
#ifndef TRUCK_H
#define TRUCK_H

#include

#include "icecream.h"
#include "macros.h"

class BINDINGS_API Truck {
public:
? ? Truck(bool leaveOnDestruction = false);
? ? Truck(const Truck &other);
? ? Truck& operator=(const Truck &other);
? ? ~Truck();

? ? void addIcecreamFlavor(Icecream *icecream);
? ? void printAvailableFlavors() const;

? ? bool deliver() const;
? ? void arrive() const;
? ? void leave() const;

? ? void setLeaveOnDestruction(bool value);
? ? void setArrivalMessage(const std::string &message);

private:
? ? void clearFlavors();

? ? bool m_leaveOnDestruction = false;
? ? std::string m_arrivalMessage = "A new icecream truck has arrived!\n";
? ? std::vector m_flavors;
};

#endif // TRUCK_H
------------------------------------------bindings.h-----------------------------------------------------

#ifndef BINDINGS_H
#define BINDINGS_H

#include "icecream.h"
#include "truck.h"

#endif // BINDINGS_H
------------------------------------------------macros.h------------------------------------------------

#ifndef MACROS_H
#define MACROS_H

#if defined _WIN32 || defined __CYGWIN__
? ? // Export symbols when creating .dll and .lib, and import them when using .lib.
? ? #if BINDINGS_BUILD
? ? ? ? #define BINDINGS_API __declspec(dllexport)
? ? #else
? ? ? ? #define BINDINGS_API __declspec(dllimport)
? ? #endif
? ? // Disable warnings about exporting STL types being a bad idea. Don't use this in production
? ? // code.
? ? #pragma warning( disable : 4251 )
#else
? ? #define BINDINGS_API
#endif

#endif // MACROS_H
------------------------------------------bindings.xml------------------------------------------------

? ?
? ?

? ?
? ? ? ?
? ? ? ?
? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ?

? ? ? ?

? ?

? ?
? ? ? ?
? ? ? ?
? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ?

? ? ? ?

? ?

--------------------------------以上為源碼----------------------------------------------------
編譯使用cmake:
CMakeLists.txt如下,(這是重點)
-----------------------------------------------------------------------------------------------
cmake_minimum_required(VERSION 3.1)
cmake_policy(VERSION 3.1)

# Enable policy to not use RPATH settings for install_name on macOS.
if(POLICY CMP0068)
? cmake_policy(SET CMP0068 NEW)
endif()

# Consider changing the project name to something relevant for you.
project(SampleBinding)


# ================================ General configuration ======================================

# Set CPP standard to C++11 minimum.
set(CMAKE_CXX_STANDARD 11)

# The sample library for which we will create bindings. You can change the name to something
# relevant for your project.
set(sample_library "libuniverse")
#設置一個庫的名稱,sample_library相當libuniverse,為了下面名稱統一,方便修改

# The name of the generated bindings module (as imported in Python). You can change the name
# to something relevant for your project.
set(bindings_library "Universe")

# The header file with all the types and functions for which bindings will be generated.
# Usually it simply includes other headers of the library you are creating bindings for.
set(wrapped_header ${CMAKE_SOURCE_DIR}/bindings.h)
#設置綁定文件,都是用一個變量來代替文件,不懂百度cmake ?set.

# The typesystem xml file which defines the relationships between the C++ types / functions
# and the corresponding Python equivalents.
set(typesystem_file ${CMAKE_SOURCE_DIR}/bindings.xml)

# Specify which C++ files will be generated by shiboken. This includes the module wrapper
# and a '.cpp' file per C++ type. These are needed for generating the module shared
# library.
set(generated_sources
? ? ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/universe_module_wrapper.cpp
? ? ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/icecream_wrapper.cpp
? ? ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/truck_wrapper.cpp)
#這個是我們生產py庫的時候需要的源文件,也就是用第二部分shiboken2生成

# ================================== Shiboken detection ======================================
# Use provided python interpreter if given.
if(NOT python_interpreter)
? ? find_program(python_interpreter "python")
endif()
message(STATUS "Using python interpreter: ${python_interpreter}")

# Macro to get various pyside / python include / link flags and paths.
# Uses the not entirely supported utils/pyside2_config.py file.
macro(pyside2_config option output_var)
? ? if(${ARGC} GREATER 2)
? ? ? ? set(is_list ${ARGV2})
? ? else()
? ? ? ? set(is_list "")
? ? endif()

? ? execute_process(
? ? ? COMMAND ${python_interpreter} "${CMAKE_SOURCE_DIR}/../utils/pyside2_config.py"
? ? ? ? ? ? ? ${option}
? ? ? OUTPUT_VARIABLE ${output_var}
? ? ? OUTPUT_STRIP_TRAILING_WHITESPACE)

? ? if ("${${output_var}}" STREQUAL "")
? ? ? ? message(FATAL_ERROR "Error: Calling pyside2_config.py ${option} returned no output.")
? ? endif()
? ? if(is_list)
? ? ? ? string (REPLACE " " ";" ${output_var} "${${output_var}}")
? ? endif()
endmacro()

# Query for the shiboken generator path, Python path, include paths and linker flags.
pyside2_config(--shiboken2-module-path shiboken2_module_path)
pyside2_config(--shiboken2-generator-path shiboken2_generator_path)
pyside2_config(--python-include-path python_include_dir)
pyside2_config(--shiboken2-generator-include-path shiboken_include_dir 1)
pyside2_config(--shiboken2-module-shared-libraries-cmake shiboken_shared_libraries 0)
pyside2_config(--python-link-flags-cmake python_linking_data 0)

set(shiboken_path "${shiboken2_generator_path}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}")
if(NOT EXISTS ${shiboken_path})
? ? message(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}")
endif()

#以上這些只是為了找出一個庫和一些需要包含的路徑,理論上可以自己直接設置,
# ==================================== RPATH configuration ====================================


# =============================================================================================
# !!! (The section below is deployment related, so in a real world application you will want to
# take care of this properly with some custom script or tool).
# =============================================================================================
# Enable rpaths so that the built shared libraries find their dependencies.
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH ${shiboken2_module_path} ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# =============================================================================================
# !!! End of dubious section.
# =============================================================================================


# =============================== CMake target - sample_library ===============================


# Define the sample shared library for which we will create bindings.
set(${sample_library}_sources icecream.cpp truck.cpp)#設置動態庫需要的源文件
add_library(${sample_library} SHARED ${${sample_library}_sources})#生成一個動態庫
set_property(TARGET ${sample_library} PROPERTY PREFIX "")

# Needed mostly on Windows to export symbols, and create a .lib file, otherwise the binding
# library can't link to the sample library.
target_compile_definitions(${sample_library} PRIVATE BINDINGS_BUILD)
#宏定義變量BINDINGS_BUILD,因為封裝庫導出需要


# ====================== Shiboken target for generating binding C++ files ?====================

#下面是設置生成器的路徑
# Set up the options to pass to shiboken.
set(shiboken_options --generator-set=shiboken --enable-parent-ctor-heuristic
? ? --enable-return-value-heuristic --use-isnull-as-nb_nonzero
? ? --avoid-protected-hack
? ? -I${CMAKE_SOURCE_DIR}
? ? -T${CMAKE_SOURCE_DIR}
? ? --output-directory=${CMAKE_CURRENT_BINARY_DIR}
? ? )

set(generated_sources_dependencies ${wrapped_header} ${typesystem_file})

# Add custom target to run shiboken to generate the binding cpp files.
add_custom_command(OUTPUT ${generated_sources}
? ? ? ? ? ? ? ? ? ? COMMAND ${shiboken_path}
? ? ? ? ? ? ? ? ? ? ${shiboken_options} ${wrapped_header} ${typesystem_file}
? ? ? ? ? ? ? ? ? ? DEPENDS ${generated_sources_dependencies}
? ? ? ? ? ? ? ? ? ? IMPLICIT_DEPENDS CXX ${wrapped_header}
? ? ? ? ? ? ? ? ? ? WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
? ? ? ? ? ? ? ? ? ? COMMENT "Running generator for ${typesystem_file}.")


# =============================== CMake target - bindings_library =============================


# Set the cpp files which will be used for the bindings library.
set(${bindings_library}_sources ${generated_sources})

# Define and build the bindings library.
add_library(${bindings_library} MODULE ${${bindings_library}_sources})

# Apply relevant include and link flags.
target_include_directories(${bindings_library} PRIVATE ${python_include_dir})
target_include_directories(${bindings_library} PRIVATE ${shiboken_include_dir})
target_include_directories(${bindings_library} PRIVATE ${CMAKE_SOURCE_DIR})

target_link_libraries(${bindings_library} PRIVATE ${shiboken_shared_libraries})
target_link_libraries(${bindings_library} PRIVATE ${sample_library})

# Adjust the name of generated module.
set_property(TARGET ${bindings_library} PROPERTY PREFIX "")
set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME
? ? ? ? ? ? ?"${bindings_library}${PYTHON_EXTENSION_SUFFIX}")
if(WIN32)
? ? set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
endif()

# Make sure the linker doesn't complain about not finding Python symbols on macOS.
if(APPLE)
? set_target_properties(${bindings_library} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif(APPLE)

# Find and link to the python import library only on Windows.
# On Linux and macOS, the undefined symbols will get resolved by the dynamic linker
# (the symbols will be picked up in the Python executable).
if (WIN32)
? ? list(GET python_linking_data 0 python_libdir)
? ? list(GET python_linking_data 1 python_lib)
? ? find_library(python_link_flags ${python_lib} PATHS ${python_libdir} HINTS ${python_libdir})
? ? target_link_libraries(${bindings_library} PRIVATE ${python_link_flags})
endif()


# ================================= Dubious deployment section ================================


if(WIN32)
? ? # =========================================================================================
? ? # !!! (The section below is deployment related, so in a real world application you will
? ? # want to take care of this properly (this is simply to eliminate errors that users usually
? ? # encounter.
? ? # =========================================================================================
? ? # Circumvent some "#pragma comment(lib)"s in "include/pyconfig.h" which might force to link
? ? # against a wrong python shared library.

? ? set(python_versions_list 3 32 33 34 35 36 37 38)
? ? set(python_additional_link_flags "")
? ? foreach(ver ${python_versions_list})
? ? ? ? set(python_additional_link_flags
? ? ? ? ? ? "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}_d.lib\"")
? ? ? ? set(python_additional_link_flags
? ? ? ? ? ? "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}.lib\"")
? ? endforeach()

? ? set_target_properties(${bindings_library}
? ? ? ? ? ? ? ? ? ? ? ? ? ?PROPERTIES LINK_FLAGS "${python_additional_link_flags}")

? ? # Add custom target to hard-link shiboken shared libraries into the build folder, so that
? ? # the user doesn't have to set the PATH manually to point to the PySide2 package.
? ? foreach(library_path ${shiboken_shared_libraries})
? ? ? ? string(REGEX REPLACE ".lib$" ".dll" library_path ${library_path})
? ? ? ? get_filename_component(base_name ${library_path} NAME)
? ? ? ? file(TO_NATIVE_PATH ${library_path} source_path)
? ? ? ? file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${base_name}" dest_path)
? ? ? ? add_custom_command(OUTPUT "${base_name}"
? ? ? ? ? ? ? ? ? ? ? ? ? ? COMMAND mklink /H "${dest_path}" "${source_path}"
? ? ? ? ? ? ? ? ? ? ? ? ? ? DEPENDS ${library_path}
? ? ? ? ? ? ? ? ? ? ? ? ? ? WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
? ? ? ? ? ? ? ? ? ? ? ? ? ? COMMENT "Creating hardlink to shiboken shared library ${base_name}")

? ? ? ? # Fake target that depends on the previous one, but has special ALL keyword, which means
? ? ? ? # it will always be executed.
? ? ? ? add_custom_target("fake_${base_name}" ALL DEPENDS ${base_name})
? ? endforeach()
? ? # =========================================================================================
? ? # !!! End of dubious section.
? ? # =========================================================================================
endif()

# =============================================================================================
# !!! (The section below is deployment related, so in a real world application you will want to
# take care of this properly with some custom script or tool).
# =============================================================================================
# Install the library and the bindings module into the source folder near the main.py file, so
# that the Python interpeter successfully imports the used module.
install(TARGETS ${bindings_library} ${sample_library}
? ? ? ? LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
? ? ? ? RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}
? ? ? ? )
# =============================================================================================
# !!! End of dubious section.
# =============================================================================================
-------------------------------------------------------------------------------------------------------------
怎么執行;把上面的文件放在一個文件夾上,然后在該文件夾上新建一個空的文件夾build,進入到build文件夾下,打開cmd命令行。然后cmake -H.. -B. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
生成一個makefile,繼續執行nmake,就能生成我們需要的庫,把生成的庫一個.dll,一個.pyd,可能還有其余pyside,shiboken放一起,或者你設置的環境變量都能找到也沒問題。

然后寫一個py調用
-----------------------------------------------------------------------------------------
from __future__ import print_function

"""An example showcasing how to use bindings for a custom non-Qt C++ library"""

from Universe import Icecream, Truck

class VanillaChocolateIcecream(Icecream):
? ? def __init__(self, flavor=""):
? ? ? ? super(VanillaChocolateIcecream, self).__init__(flavor)

? ? def clone(self):
? ? ? ? return VanillaChocolateIcecream(self.getFlavor())

? ? def getFlavor(self):
? ? ? ? return "vanilla sprinked with chocolate"

class VanillaChocolateCherryIcecream(VanillaChocolateIcecream):
? ? def __init__(self, flavor=""):
? ? ? ? super(VanillaChocolateIcecream, self).__init__(flavor)

? ? def clone(self):
? ? ? ? return VanillaChocolateCherryIcecream(self.getFlavor())

? ? def getFlavor(self):
? ? ? ? base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor()
? ? ? ? return base_flavor + " and a cherry"

if __name__ == '__main__':
? ? leave_on_destruction = True
? ? truck = Truck(leave_on_destruction)

? ? flavors = ["vanilla", "chocolate", "strawberry"]
? ? for f in flavors:
? ? ? ? icecream = Icecream(f)
? ? ? ? truck.addIcecreamFlavor(icecream)

? ? truck.addIcecreamFlavor(VanillaChocolateIcecream())
? ? truck.addIcecreamFlavor(VanillaChocolateCherryIcecream())

? ? truck.arrive()
? ? truck.printAvailableFlavors()
? ? result = truck.deliver()

? ? if result:
? ? ? ? print("All the kids got some icecream!")
? ? else:
? ? ? ? print("Aww, someone didn't get the flavor they wanted...")

? ? if not result:
? ? ? ? special_truck = Truck(truck)
? ? ? ? del truck

? ? ? ? print("")
? ? ? ? special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n")
? ? ? ? special_truck.arrive()
? ? ? ? special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream"))
? ? ? ? special_truck.printAvailableFlavors()
? ? ? ? special_truck.deliver()
? ? ? ? print("Now everyone got the flavor they wanted!")
? ? ? ? special_truck.leave()

--------------------------------------------------------------------------------------------------
在制作過程中可能遇到很多問題:
問題1:遇到一些編譯器問題,環境變量設置不對,調用不到自己需要的編譯器,這個一般是出現在生成makefile的過程中出現,找出你電腦中安裝的vs等編譯器中vcvars32.bat,這種批量處理的腳本,在控制臺執行就會幫助你配置一些庫和exe的調用。

問題2:解析xml或者是.h時候出錯。.h問題一般是沒有在cmake中設置包含,或者是沒有包含相關文件夾。
xml問題可能會找不到shiboken,那就是可能電腦沒有安裝shiboken2_generator的生成器。
生成過程中需要暴露的東西,需要在xml說明。bindings.h包含相關頭文件.
https://download.qt.io/official_releases/QtForPython/shiboken2-generator/
這個鏈接是生成器的下載路徑,選擇對于版本。
xml頭綁定的一些規則:
http://pyside.github.io/docs/api-extractor/typesystem.html
生成器的一些參數設置:http://pyside.github.io/docs/shiboken/

上面需要安裝的東西:最基本的,pyside2,shiboken,cmake,shiboken2_generator,vs或者其他編譯器.
上面例子可在你安裝的D:\PyThon3.5\Lib\site-packages\PySide2\examples\samplebinding

下一篇記錄一下封裝qt的例子。

源文件下載:https://download.csdn.net/download/dreamsongo/11259578

?

?

?

?

?

?

?

?

?

?

?

?

?

?


?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产成人综合网在线观看 | 中文有码第一页 | 波多野结衣亚洲一区 | 久久香蕉国产线 | 精品久久久久久乐 | 国产亚洲玖玖玖在线观看 | 99精品国产第一福利网站 | 久久久亚洲欧美综合 | 色综合久久久久 | 蘑菇视频绿巨人小黄鸭 | 乱色欧美videos黑人 | 精品久久久久久中文字幕网 | 日本不卡免费一区 | 青青草一区二区免费精品 | 日韩一区三区 | 午夜性色福利视频在线视频 | 成人夜色视频在线观看网站 | 久热伊人 | 奇米视频在线观看 | 91探花国产综合在线精品 | 国产高清不卡视频 | 久久国产精品免费看 | 久久综合久久精品 | 青青青爽视频在线观看 | 中文字幕视频免费 | 最新日本中文字幕 | 欧美久久一区二区 | 久久99精品久久久久久h | 久久日韩 | 九九夜色 | 狠狠色噜噜狠狠狠狠色吗综合 | 99热久久国产精品免费观看 | 欧美一级毛片一级 | 亚洲欧美日韩在线不卡 | 久久久久久久综合日本亚洲 | 偷自拍视频区综合视频区 | 高清国产精品入口麻豆 | 日日夜夜精品免费视频 | 欧美高清免费精品国产自 | 成人短视频在线免费观看 | 日韩伦理在线视频 |