构建

  1. 为了在C++项目下直接测试该DLL,在头文件中也需要暴露dll的API.

    如果需要生成python可调用的pyd模块, 需要include python解释器的include目录和boost目录、site-packages下的pybind11de include目录,

    另外还需要添加python的libs目录和boost目录下的编译完的stage下的lib目录。
    链接python*.lib
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>
#define NOMINMAX

#include<pybind11/pybind11.h>
#undef max//放在<pybind11/numpy.h>之前(#define NOMINMAX有时不起作用)
#include<pybind11/numpy.h>

#define EXPORT_DLL __declspec(dllexport)


class EXPORT_DLL className
{
className(int value);
~className();

void finction(int a);

}

extern "C" EXPORT_DLL className* className_new(int value);
extern "C" EXPORT_DLL void className_delete(className* instance);
extern "C" EXPORT_DLL void className_function(className* instance,int a);

  1. .cpp
    源文件中暴露python可调用的接口,代码实现后
PYBIND11_MODULE(className, m) {
py::class_<className>(m, "className")
.def(py::init<int>(), py::arg("size"), "***")
.def("function", &className::function, py::arg("a"), "***")
.def_readonly("m_outputRe", &className::m_outputRe) // 暴露可访问的变量,可设置是否可读可写
.def_readonly("m_outputIm", &className::m_outputIm);
}

测试

  1. 设置好dll项目的生成后事件,将生成好的链接库拷贝到指定目录,例如

    xcopy /y /d “$(OutDir)fixedFFTDLL.pyd” “$(SolutionDir)..\DLLTest\bin”

  2. 随后在测试项目中链接该库,但是一般写给python调用的库都是需要传入python中的变量把比如numpy的数组,这时候需要在测试项目中添加python的目录和链接库,参考构建。

    此外还需要include对应的numpy

// #include ...
#include <pybind11/numpy.h>
namespace py = pybind11;
using namespace std;
namespace bp = boost::python;

void set_env(const std::string& key, const std::string& value);
void set_env(const std::string& key, const std::string& value)
{
std::string env_var = key + "=" + value;
_putenv(env_var.c_str());
}

int main()
{
set_env("PYTHONHOME", "C:/Interpreter/Python"); // 设置python的环境
set_env("PYTHONPATH", "C:/Interpreter/Python/Lib;G:/PIP_ENV_PROJECT/ENV/Lark-NtTz9GWT/Lib/site-packages");
try // 必须要用try语句捕获python的异常
{
py::scoped_interpreter guard{};
/*
对待测试的dll的调用
*/
}
catch (const py::error_already_set& e)
{
std::cerr << "Python exception: " << e.what() << std::endl;
return 1; // 非零返回值表示错误
}
catch (const std::exception& e)
{
std::cerr << "Standard exception: " << e.what() << std::endl;
return 1; // 非零返回值表示错误
}
catch (...)
{
std::cerr << "Unknown exception occurred" << std::endl;
return 1; // 非零返回值表示错误
}
}