文章目录
- Part.I Introduction
- Chap.I CMakeLists
- Chap.II ExportLibGSL.h
- Chap.III test_python.cpp
- Part.II GSL 使用方法
- Part.III C++ 调用 Python 使用方法
- 相关博客
Part.I Introduction
本项目是一个使用 GSL 的小项目,还有 C++ 调用 Python。项目虽简单,但麻雀虽小五脏俱全,笔者觉得此项目架构还是比较明晰的,值得一看。本文档将介绍如何使用此项目。
项目所包含文件如下:
.─app_test
│ ├─TEMP_TestGSL
│ └─TEMP_TestPython
├─LibGSL
│ ├─example
│ └─gexport
├─LibPython
│ ├─example
│ │ └─__pycache__
│ └─gexport
└─_doc
请戳我(要钱的哦)下载,下面展示部分文件
Chap.I CMakeLists
下面是一个主 CMakeLists。
# 要求的 CMAKE 最低版本号
cmake_minimum_required(VERSION 3.0.0)
# 项目名和版本号
project(Temp VERSION 1.0.0)
# information message# 编译器设置
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)# 编译选项设置
if(CMAKE_SYSTEM_NAME MATCHES "Windows")SET(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}_Windows)add_compile_options(/bigobj)add_compile_options(/MP)add_compile_options(/w)
endif()if(COMPILER_SUPPORTS_CXX11)set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED ON)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
elseif(COMPILER_SUPPORTS_CXX0X)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread")
else()message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()# Choose different compilation configurations according to VS compilation
# 根据VS编译选择不同的编译配置
if(CMAKE_BUILD_TYPE MATCHES "Release")set(CMAKE_BUILD_POSTFIX "${CMAKE_RELEASE_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "Debug")set(CMAKE_BUILD_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")set(CMAKE_BUILD_POSTFIX "${CMAKE_RELWITHDEBINFO_POSTFIX}")
elseif(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")set(CMAKE_BUILD_POSTFIX "${CMAKE_MINSIZEREL_POSTFIX}")
else()set(CMAKE_BUILD_POSTFIX "")
endif()# Set the ROOT and subdirectory, you should put the CMakeList.txt in these file directories
# 设置根目录和子目录时,应将CMakeList.txt文件在这些文件目录中
set(ROOT ${PROJECT_SOURCE_DIR})
set(EXECUTABLE_OUTPUT_PATH ${BUILD_DIR}/Bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BUILD_DIR}/Bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BUILD_DIR}/Lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_DIR}/Lib)set(CMAKE_DEBUG_POSTFIX "d")
set(CMAKE_RELEASE_POSTFIX "")
set(CMAKE_RELWITHDEBINFO_POSTFIX "rd")
set(CMAKE_MINSIZEREL_POSTFIX "s")# 为调试Cmake输出消息
message(STATUS "operation system is : ${CMAKE_SYSTEM}")
message(STATUS "current platform is : ${CMAKE_SYSTEM_NAME}")
message(STATUS "CMake version is : ${CMAKE_SYSTEM_VERSION}")
message(STATUS "C compiler is : ${CMAKE_C_COMPILER}")
message(STATUS "C++ compiler is : ${CMAKE_CXX_COMPILER}")
message(STATUS "Build directory is : ${BUILD_DIR}")
message(STATUS "The program main directory is : ${ROOT}")# 设置一些文件夹,库里面的 CMake 会用到
set(file_fold example gexport)
set(PrintFile FALSE)# ==================================================================================
# 为了测试 Python,各位不用开即可
option(Main_USE_PYTHON "using " OFF)# 链接三方库
if(CMAKE_SYSTEM_NAME MATCHES "Windows")#For windows# ==============================================================================if (NOT DEFINED Third_GSL_ROOT)find_path(Third_GSL_ROOT HINTS "${Third_GSL_ROOT}" "$ENV{Third_GSL_ROOT} ")endif()# ==============================================================================
endif()set(LibGSL LibGSL)
set(LibGSLSrc ${ROOT}/${LibGSL})
add_subdirectory(${LibGSLSrc} ${BUILD_DIR}/${LibGSL})
SET_PROPERTY(TARGET ${LibGSL} PROPERTY FOLDER "LIB")if(Main_USE_PYTHON)set(LibPython LibPython)set(LibPythonSrc ${ROOT}/${LibPython})add_subdirectory(${LibPythonSrc} ${BUILD_DIR}/${LibPython})SET_PROPERTY(TARGET ${LibPython} PROPERTY FOLDER "LIB")
endif()# 使用文件夹选项打开
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
Chap.II ExportLibGSL.h
#ifndef EXPORT_LibGSL_H
#define EXPORT_LibGSL_H#if defined(_MSC_VER)
#pragma warning(disable : 4244)
#pragma warning(disable : 4251)
#pragma warning(disable : 4275)
#pragma warning(disable : 4512)
#pragma warning(disable : 4267)
#pragma warning(disable : 4702)
#pragma warning(disable : 4511)
#pragma warning(disable : 4996)
#endif#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BCPLUSPLUS__) || defined(__MWERKS__)
#if defined(TEMP_LibGSL_LIBRARY)
#define LibGSL_LIBRARY_EXPORT __declspec(dllexport)
#else
#define LibGSL_LIBRARY_EXPORT __declspec(dllimport)
#endif
#else
#define LibGSL_LIBRARY_EXPORT
#endif#ifdef _MSC_VER
#if (_MSC_VER >= 1300)
#define __STL_MEMBER_TEMPLATES
#endif
#endif#include <string>
#include <vector>
using namespace std;#ifndef SIZE_INT
#define SIZE_INT sizeof(int)
#endif#ifndef SIZE_DBL
#define SIZE_DBL sizeof(double)
#endif // !SIZE_DBL
#endif
Chap.III test_python.cpp
C++ 调用 Python 的主要代码
#include <iostream>
#include "test_python.h"using namespace std;namespace temp
{t_test_python::t_test_python() { }t_test_python::~t_test_python(){}int t_test_python::_pythonInit() {Py_Initialize();int ret = Py_IsInitialized();if (ret == 0) {cout << "Py_Initialize error" << endl;return kError;}return kSuccess;}void t_test_python::_pythonCleanup() {Py_Finalize();}int t_test_python::_callPythonAdd(PyObject* module, int a, int b) {//获取模块字典属性PyObject* pDict = PyModule_GetDict(module);if (pDict == nullptr) {PyErr_Print();std::cout << "PyModule_GetDict error" << std::endl;return kError;}//直接获取模块中的函数PyObject* addFunc = PyDict_GetItemString(pDict, "add");if (addFunc == nullptr) {std::cout << "PyDict_GetItemString 'add' not found" << std::endl;return kError;}// 构造python 函数入参, 接收2// see: https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=pyarg_parse#c.PyArg_ParsePyObject* pArg = Py_BuildValue("(i,i)", a, b);//调用函数,并得到 python 类型的返回值PyObject* result = PyEval_CallObject(addFunc, pArg);int ret = 0;//将python类型的返回值转换为c/c++类型PyArg_Parse(result, "i", &ret);return ret;}PyObject* t_test_python::_pythonImportModule(const char* pyDir, const char* name) {// 引入当前路径,否则下面模块不能正常导入char tempPath[256] = {};sprintf(tempPath, "sys.path.append('%s')", pyDir);PyRun_SimpleString("import sys");//PyRun_SimpleString("sys.path.append('./')");PyRun_SimpleString(tempPath);PyRun_SimpleString("print('----------------------------------------')");PyRun_SimpleString("print('curr sys.path: ', sys.path)");PyRun_SimpleString("print('----------------------------------------')");// import ${name}PyObject* module = PyImport_ImportModule(name);if (module == nullptr) {PyErr_Print();cout << "PyImport_ImportModule '" << name << "' not found" << endl;return nullptr;}return module;}int t_test_python::_callPythonGetName(PyObject* module, std::string firstName, std::string& outName) {//获取模块字典属性PyObject* pDict = PyModule_GetDict(module);if (pDict == nullptr) {PyErr_Print();std::cout << "PyModule_GetDict error" << std::endl;return kError;}//直接获取模块中的函数PyObject* addFunc = PyDict_GetItemString(pDict, "get_name");if (addFunc == nullptr) {std::cout << "PyDict_GetItemString 'add' not found" << std::endl;return kError;}// 构造python 函数入参, 接收2// see: https://docs.python.org/zh-cn/3.7/c-api/arg.html?highlight=pyarg_parse#c.PyArg_ParsePyObject* pArg = Py_BuildValue("(s)", firstName.c_str());//调用函数,并得到python类型的返回值PyObject* result = PyEval_CallObject(addFunc, pArg);char* name = nullptr;//将python类型的返回值转换为c/c++类型PyArg_Parse(result, "s", &name);char tempStr[256] = {};int strLen = strlen(name);if (strLen > 256) {return kError;}strcpy(tempStr, name);outName = tempStr;return kSuccess;}int t_test_python::processBatch(){_pythonInit();//直接运行 python 代码PyRun_SimpleString("print('---------- Hello Python form C/C++ ----------')");PyRun_SimpleString("print('Test BEGIN ...')");//调用 Python 脚本PyObject* helloModule = _pythonImportModule("A:/aWork/scripts/AURORA/V1/LibPython/example", "hello"); // 这里最好还是给绝对路径吧if (helloModule == nullptr) {return -1;}// call python add functionint result = _callPythonAdd(helloModule, 1, 3);cout << "1 + 3 = " << result << endl;// call python get_name functionstd::string fullName;_callPythonGetName(helloModule, "Summer", fullName);cout << fullName << endl;PyRun_SimpleString("print('Test END!')");_pythonCleanup();}
}
Part.II GSL 使用方法
首先需要安装 CMake、VS Studio
为了防止不必要的歧义,下面将项目的根目录称为『当前目录』
首先将_doc
文件夹下的gsl.zip
解压,放到一个你不常动的目录中,将这个目录(或 这个目录/gsl)称为『gsl目录』,懂我意思吧
1、在当前目录下新建 build
文件夹
2、打开 CMake,源码路径设置为当前目录,build 路径设置为 当前目录/build
3、点击 Configure
,之后配置根据自己实际情况配,配好点击 Finish
4、会报错,不要急,把 gsl 目录赋给 Third_GSL_ROOT
,再次点击Configure
5、依次点击Generate
和Open Project
,打开项目
6、将 TEMP_TestGSL
设为启动项目
7、快捷键 F5
运行,得到结果
完事!
Part.III C++ 调用 Python 使用方法
1、上面第三步勾选 Main_USE_PYTHON
,把 Python 的路径给它
2、依次点击Configure
、Generate
和Open Project
,打开项目
3、将 TEMP_TestPython
设为启动项目
4、快捷键 F5
运行,得到结果
完事!
相关博客
- C/C++ 之 GSL 数学运算库使用笔记
- Windows 下用 C++ 调用 Python