文章目录
- 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_Parse
PyObject* 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_Parse
PyObject* 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 function
int result = _callPythonAdd(helloModule, 1, 3);
cout << "1 + 3 = " << result << endl;
// call python get_name function
std::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