如何将 Numpy 矩阵列表映射到 Cython 中的特征矩阵向量
How to map a list of Numpy matrices to a vector of Eigen matrices in Cython
我有一个 C++ 函数,我想从 Python 运行。为此,我使用 Cython。
我的 C++ 函数在很大程度上依赖于特征矩阵,我使用特征映射到 Python 的 Numpy 矩阵。
如果我有一个 Numpy 矩阵列表,我无法让它工作。
什么有效(将普通 Numpy 矩阵映射到特征矩阵):
我有一个 C++ 函数,在 header (Header.h) 中看起来像:
float MyCppFunction(Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> &inputMatrix);
在我的 CythonFile.pyx 文件中(并按照 here 的说明使用 Eigency 创建地图):
cdef extern from "Header.h":
cdef void _MyCppFunction "MyCppFunction"(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] &)
和
def my_python_function(np.ndarray[ndim=2, dtype=np.float32_t] my_matrix)
return _MyCppFunction(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix))
我可以使用 Cython 构建此模块并从 Python 成功调用 my_python_function
。
什么不起作用(将 Numpy 矩阵列表映射到特征矩阵向量):
现在我尝试做同样的事情,但对于矩阵列表。我无法让它工作。
我有:
header (Header.h) 中的 C++ 函数如下所示:
float MyCppFunction(std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>> &inputMatrixList);
在我的 CythonFile.pyx 文件中我有:
cdef extern from "Header.h":
cdef void _MyCppFunction "MyCppFunction"(vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &)
和
def my_python_function(list my_matrix_list)
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] map
for matrix in my_matrix_list:
map.push_back(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](matrix))
return _MyCppFunction(map)
不幸的是,这不会编译。
这个概念确实编译并且 运行 当我,例如,简单地使用 int
的 list
,我想映射到 std::vector<int>
。但是,当我将 Numpy-matrices 的列表映射到特征矩阵的向量(我在上面提到的情况)时,它不起作用。
我得到的错误:
我在编译过程中得到的错误:
error C2664: 'float MyCppFunction(std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>,std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>> &)': cannot convert argument 1 from 'std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>,std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>' to 'std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>,std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>> &' ./Header.h(21): note: see declaration of 'MyCppFunction'
我目前的分析:
这按预期工作,因此:我可以将 int
的 python list
分配给 C++ std::vector<int>
.
这也按预期工作,因此:我可以将类型 eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>
的变量分配给类型 Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>
的变量。
当我将后两个变量包装在 list/vector 中时,我无法为这些变量赋值:
std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>, std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>
到 std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>, std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>>
.
类型的变量
也许它与分配器部分有关,但我不知道,因为我不是真正的 C++ 专家。
有人有将 Numpy 矩阵列表映射到特征矩阵向量的解决方案吗?最好遵循与上述相同的模式,但也欢迎其他解决方案。
我要复现的源代码:
下面是我用来测试的源码。它有一个接受普通 Eigen/Numpy 矩阵的函数,以及一个接受 Vector/List 的 Eigen/Numpy 矩阵的函数。
如果您注释掉向量变体的所有段落,代码将编译。否则,我会收到编译错误。我在编译时遇到的(第一个)编译错误是:.\source_cpp_cython/cpp_source_cpp.h(16): error C2065: 'FlattenedMapWithOrder': undeclared identifier
.
我在 Windows 上使用 Microsoft Visual Studio 编译器 (MSVC) 2019。如果相关,我还使用 Eigen 版本 3.4.0-rc1。
cython_source.pyx
# distutils: language = c++
# distutils: sources = source_cpp_cython/cpp_source_cpp.cpp
from eigency.core cimport * # Docs: https://pypi.org/project/eigency/1.4/
from libcpp.vector cimport vector
import numpy as np
cimport numpy
cdef extern from "source_cpp_cython/cpp_source_cpp.h":
cdef float _MyCppFunction "MyCppFunction"(
FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] &
)
cdef float _MyCppFunctionVector "MyCppFunctionVector"(
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &
)
def my_python_function(np.ndarray[ndim=2, dtype=np.float32_t] my_matrix):
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp
my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix)
return _MyCppFunction(my_matrix_cpp)
def my_python_function_vector(list my_matrix_list):
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp
for my_matrix in my_matrix_list:
my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix)
matrix_map_vec.push_back(my_matrix_cpp)
return _MyCppFunctionVector(matrix_map_vec)
cpp_source_cpp.h
#pragma once
#include <Eigen/Dense>
#include <Eigen/Core>
#include <vector>
#include <numpy/ndarraytypes.h>
#include <complex>
typedef ::std::complex< double > __pyx_t_double_complex;
typedef ::std::complex< float > __pyx_t_float_complex;
#include "eigency_cpp.h"
float MyCppFunction(
const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix
);
float MyCppFunctionVector(
const std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList
);
cpp_source_cpp.cpp
#include "cpp_source_cpp.h"
float MyCppFunction(
const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix
)
{
// std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>> test;
return 5.0;
}
float MyCppFunctionVector(
const std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList
)
{
//Convert FlattenedMap to Eigen-Map.
std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> convertedMatrixList(
inputMatrixList.begin(), inputMatrixList.end() );
return 6.0;
}
我的cython设置文件setup_cython_module.py中的相关段落是:
# Some constants
SOURCE_FOLDER_NAME = "source_cpp_cython"
OUTPUT_FOLDER_NAME = "cython_module"
# Build extensions list
extensions = [
Extension(f"{OUTPUT_FOLDER_NAME}.{OUTPUT_FOLDER_NAME}",
[f"{SOURCE_FOLDER_NAME}/cython_source.pyx"],
include_dirs=["."] + [f"{SOURCE_FOLDER_NAME}"]
+ [f"{SOURCE_FOLDER_NAME}\Eigen"] + eigency.get_includes(include_eigen=False)
+ [numpy.get_include()],
language='c++',
# extra_compile_args=['/MT'], # To let the Microsoft compiler use a specific lib for threading required by OpenCV.
)
]
# Build cython package
dist = setup(
name=f"{OUTPUT_FOLDER_NAME}",
version="1.0",
ext_modules=cythonize(extensions, language_level="3"), # , gdb_debug=True),
packages=[f"{OUTPUT_FOLDER_NAME}"]
)
Cython 的完整日志输出:
Created output directory: D:\Default_Folders\Documents\Development\RepoStefan\CythonTest\cython_module
running build_ext
building 'cython_module.cython_module' extension
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IC:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\eigency -I. -Isource_cpp_cython -Isource_cpp_cython\Eigen -IC:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\numpy\core\include -IC:\ProgramData\Miniconda3\envs\cenv38rl\include -IC:\ProgramData\Miniconda3\envs\cenv38rl\include "-IC:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK.8\include\um" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\shared" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\um" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\winrt" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\cppwinrt" /EHsc /Tpsource_cpp_cython/cython_source.cpp /Fobuild\temp.win-amd64-3.8\Release\source_cpp_cython/cython_source.obj /MT
cl : Command line warning D9025 : overriding '/MD' with '/MT'
cython_source.cpp
C:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(14) : Warning Msg: Using deprecated NumPy API, disable it with #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
.\source_cpp_cython/cpp_source_cpp.h(17): error C2065: 'FlattenedMapWithOrder': undeclared identifier
.\source_cpp_cython/cpp_source_cpp.h(17): error C2275: 'Eigen::Matrix<float,-1,-1,1,-1,-1>': illegal use of this type as an expression
.\source_cpp_cython/cpp_source_cpp.h(17): note: see declaration of 'Eigen::Matrix<float,-1,-1,1,-1,-1>'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2974: 'std::vector': invalid template argument for '_Ty', type expected
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include\vector(443): note: see declaration of 'std::vector'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2976: 'std::vector': too few template arguments
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include\vector(443): note: see declaration of 'std::vector'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2143: syntax error: missing ')' before '>'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2059: syntax error: '>'
.\source_cpp_cython/cpp_source_cpp.h(18): error C2059: syntax error: ')'
source_cpp_cython/cython_source.cpp(1964): error C2664: 'float MyCppFunctionVector(const std::vector)': cannot convert argument 1 from 'std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>,std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>' to 'const std::vector'
source_cpp_cython/cython_source.cpp(1964): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
.\source_cpp_cython/cpp_source_cpp.h(16): note: see declaration of 'MyCppFunctionVector'
error: command 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\HostX86\x64\cl.exe' failed with exit status 2
Process finished with exit code 1
非常感谢!
感谢@ead,我找到了解决方案。
FlattenedMapWithOrder
有实现,因此可以分配给 Eigen::Matrix
。
但是,std::vector
没有这样的功能,并且由于 std::vector<FlattenedMapWithOrder>
和 std::vector<Eigen::Matrix>
是不同的类型,因此不能将它们分配给彼此。
有关此内容的更多信息 here。
上面提到的FlattenedMapWithOrder
中的实现是here.
为了解决这个问题,从 Cython 调用的 C++ 代码中的函数需要简单地将匹配类型作为输入参数:std::vector<FlattenedMapWithOrder>
。
为此,C++ 代码需要知道类型 FlattenedMapWithOrder
.
的定义
为此,您需要 #include "eigency_cpp.h"
。不幸的是,这个 header 不是独立的。
因此,(感谢@ead)我添加了这些行:
#include <numpy/ndarraytypes.h>
#include <complex>
typedef ::std::complex< double > __pyx_t_double_complex;
typedef ::std::complex< float > __pyx_t_float_complex;
#include "eigency_cpp.h"
使用它,我能够在我的 C++ 代码中声明这个函数:
void MyCppFunctionVector(
const std::vector<eigency::FlattenedMap<Eigen::Matrix, float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrixList,
std::vector<eigency::FlattenedMap<Eigen::Matrix, float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& outputMatrixList
);
我的 *.pxy 文件看起来像:
cdef extern from "source_cpp_cython/cpp_source_cpp.h":
cdef void _MyCppFunctionVector "MyCppFunctionVector"(
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &,
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &
)
def my_python_function_vector(
list my_matrix_list_input,
list my_matrix_list_output
):
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec_input
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_input_cpp
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec_output
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_output_cpp
# Convert input matrix to C++ type.
for my_matrix_input in my_matrix_list_input:
my_matrix_input_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix_input)
matrix_map_vec_input.push_back(my_matrix_input_cpp)
for my_matrix_output in my_matrix_list_output:
my_matrix_output_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix_output)
matrix_map_vec_output.push_back(my_matrix_output_cpp)
# Call the C++ function.
_MyCppFunctionVector(matrix_map_vec_input, matrix_map_vec_output)
return my_matrix_list_output
就是这样。
我有一个 C++ 函数,我想从 Python 运行。为此,我使用 Cython。 我的 C++ 函数在很大程度上依赖于特征矩阵,我使用特征映射到 Python 的 Numpy 矩阵。
如果我有一个 Numpy 矩阵列表,我无法让它工作。
什么有效(将普通 Numpy 矩阵映射到特征矩阵):
我有一个 C++ 函数,在 header (Header.h) 中看起来像:
float MyCppFunction(Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> &inputMatrix);
在我的 CythonFile.pyx 文件中(并按照 here 的说明使用 Eigency 创建地图):
cdef extern from "Header.h":
cdef void _MyCppFunction "MyCppFunction"(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] &)
和
def my_python_function(np.ndarray[ndim=2, dtype=np.float32_t] my_matrix)
return _MyCppFunction(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix))
我可以使用 Cython 构建此模块并从 Python 成功调用 my_python_function
。
什么不起作用(将 Numpy 矩阵列表映射到特征矩阵向量):
现在我尝试做同样的事情,但对于矩阵列表。我无法让它工作。 我有:
header (Header.h) 中的 C++ 函数如下所示:
float MyCppFunction(std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>> &inputMatrixList);
在我的 CythonFile.pyx 文件中我有:
cdef extern from "Header.h":
cdef void _MyCppFunction "MyCppFunction"(vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &)
和
def my_python_function(list my_matrix_list)
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] map
for matrix in my_matrix_list:
map.push_back(FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](matrix))
return _MyCppFunction(map)
不幸的是,这不会编译。
这个概念确实编译并且 运行 当我,例如,简单地使用 int
的 list
,我想映射到 std::vector<int>
。但是,当我将 Numpy-matrices 的列表映射到特征矩阵的向量(我在上面提到的情况)时,它不起作用。
我得到的错误:
我在编译过程中得到的错误:
error C2664: 'float MyCppFunction(std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>,std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>> &)': cannot convert argument 1 from 'std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>,std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>' to 'std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>,std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>> &' ./Header.h(21): note: see declaration of 'MyCppFunction'
我目前的分析:
这按预期工作,因此:我可以将 int
的 python list
分配给 C++ std::vector<int>
.
这也按预期工作,因此:我可以将类型 eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>
的变量分配给类型 Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>
的变量。
当我将后两个变量包装在 list/vector 中时,我无法为这些变量赋值:
std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>, std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>
到 std::vector<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>, std::allocator<Eigen::Map<Eigen::Matrix<float,-1,-1,1,-1,-1>,0,Eigen::Stride<0,0>>>>
.
也许它与分配器部分有关,但我不知道,因为我不是真正的 C++ 专家。 有人有将 Numpy 矩阵列表映射到特征矩阵向量的解决方案吗?最好遵循与上述相同的模式,但也欢迎其他解决方案。
我要复现的源代码:
下面是我用来测试的源码。它有一个接受普通 Eigen/Numpy 矩阵的函数,以及一个接受 Vector/List 的 Eigen/Numpy 矩阵的函数。
如果您注释掉向量变体的所有段落,代码将编译。否则,我会收到编译错误。我在编译时遇到的(第一个)编译错误是:.\source_cpp_cython/cpp_source_cpp.h(16): error C2065: 'FlattenedMapWithOrder': undeclared identifier
.
我在 Windows 上使用 Microsoft Visual Studio 编译器 (MSVC) 2019。如果相关,我还使用 Eigen 版本 3.4.0-rc1。
cython_source.pyx
# distutils: language = c++
# distutils: sources = source_cpp_cython/cpp_source_cpp.cpp
from eigency.core cimport * # Docs: https://pypi.org/project/eigency/1.4/
from libcpp.vector cimport vector
import numpy as np
cimport numpy
cdef extern from "source_cpp_cython/cpp_source_cpp.h":
cdef float _MyCppFunction "MyCppFunction"(
FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] &
)
cdef float _MyCppFunctionVector "MyCppFunctionVector"(
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &
)
def my_python_function(np.ndarray[ndim=2, dtype=np.float32_t] my_matrix):
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp
my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix)
return _MyCppFunction(my_matrix_cpp)
def my_python_function_vector(list my_matrix_list):
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp
for my_matrix in my_matrix_list:
my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix)
matrix_map_vec.push_back(my_matrix_cpp)
return _MyCppFunctionVector(matrix_map_vec)
cpp_source_cpp.h
#pragma once
#include <Eigen/Dense>
#include <Eigen/Core>
#include <vector>
#include <numpy/ndarraytypes.h>
#include <complex>
typedef ::std::complex< double > __pyx_t_double_complex;
typedef ::std::complex< float > __pyx_t_float_complex;
#include "eigency_cpp.h"
float MyCppFunction(
const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix
);
float MyCppFunctionVector(
const std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList
);
cpp_source_cpp.cpp
#include "cpp_source_cpp.h"
float MyCppFunction(
const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix
)
{
// std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>> test;
return 5.0;
}
float MyCppFunctionVector(
const std::vector<FlattenedMapWithOrder<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList
)
{
//Convert FlattenedMap to Eigen-Map.
std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> convertedMatrixList(
inputMatrixList.begin(), inputMatrixList.end() );
return 6.0;
}
我的cython设置文件setup_cython_module.py中的相关段落是:
# Some constants
SOURCE_FOLDER_NAME = "source_cpp_cython"
OUTPUT_FOLDER_NAME = "cython_module"
# Build extensions list
extensions = [
Extension(f"{OUTPUT_FOLDER_NAME}.{OUTPUT_FOLDER_NAME}",
[f"{SOURCE_FOLDER_NAME}/cython_source.pyx"],
include_dirs=["."] + [f"{SOURCE_FOLDER_NAME}"]
+ [f"{SOURCE_FOLDER_NAME}\Eigen"] + eigency.get_includes(include_eigen=False)
+ [numpy.get_include()],
language='c++',
# extra_compile_args=['/MT'], # To let the Microsoft compiler use a specific lib for threading required by OpenCV.
)
]
# Build cython package
dist = setup(
name=f"{OUTPUT_FOLDER_NAME}",
version="1.0",
ext_modules=cythonize(extensions, language_level="3"), # , gdb_debug=True),
packages=[f"{OUTPUT_FOLDER_NAME}"]
)
Cython 的完整日志输出:
Created output directory: D:\Default_Folders\Documents\Development\RepoStefan\CythonTest\cython_module
running build_ext
building 'cython_module.cython_module' extension
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IC:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\eigency -I. -Isource_cpp_cython -Isource_cpp_cython\Eigen -IC:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\numpy\core\include -IC:\ProgramData\Miniconda3\envs\cenv38rl\include -IC:\ProgramData\Miniconda3\envs\cenv38rl\include "-IC:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK.8\include\um" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\shared" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\um" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\winrt" "-IC:\Program Files (x86)\Windows Kits\include.0.19041.0\cppwinrt" /EHsc /Tpsource_cpp_cython/cython_source.cpp /Fobuild\temp.win-amd64-3.8\Release\source_cpp_cython/cython_source.obj /MT
cl : Command line warning D9025 : overriding '/MD' with '/MT'
cython_source.cpp
C:\ProgramData\Miniconda3\envs\cenv38rl\lib\site-packages\numpy\core\include\numpy\npy_1_7_deprecated_api.h(14) : Warning Msg: Using deprecated NumPy API, disable it with #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
.\source_cpp_cython/cpp_source_cpp.h(17): error C2065: 'FlattenedMapWithOrder': undeclared identifier
.\source_cpp_cython/cpp_source_cpp.h(17): error C2275: 'Eigen::Matrix<float,-1,-1,1,-1,-1>': illegal use of this type as an expression
.\source_cpp_cython/cpp_source_cpp.h(17): note: see declaration of 'Eigen::Matrix<float,-1,-1,1,-1,-1>'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2974: 'std::vector': invalid template argument for '_Ty', type expected
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include\vector(443): note: see declaration of 'std::vector'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2976: 'std::vector': too few template arguments
C:\Program Files (x86)\Microsoft Visual Studio19\Community\VC\Tools\MSVC.29.30037\include\vector(443): note: see declaration of 'std::vector'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2143: syntax error: missing ')' before '>'
.\source_cpp_cython/cpp_source_cpp.h(17): error C2059: syntax error: '>'
.\source_cpp_cython/cpp_source_cpp.h(18): error C2059: syntax error: ')'
source_cpp_cython/cython_source.cpp(1964): error C2664: 'float MyCppFunctionVector(const std::vector)': cannot convert argument 1 from 'std::vector<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>,std::allocator<eigency::FlattenedMap<Eigen::Matrix,float,-1,-1,1,0,0,0,-1,-1>>>' to 'const std::vector'
source_cpp_cython/cython_source.cpp(1964): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
.\source_cpp_cython/cpp_source_cpp.h(16): note: see declaration of 'MyCppFunctionVector'
error: command 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\HostX86\x64\cl.exe' failed with exit status 2
Process finished with exit code 1
非常感谢!
感谢@ead,我找到了解决方案。
FlattenedMapWithOrder
有实现,因此可以分配给 Eigen::Matrix
。
但是,std::vector
没有这样的功能,并且由于 std::vector<FlattenedMapWithOrder>
和 std::vector<Eigen::Matrix>
是不同的类型,因此不能将它们分配给彼此。
有关此内容的更多信息 here。
上面提到的FlattenedMapWithOrder
中的实现是here.
为了解决这个问题,从 Cython 调用的 C++ 代码中的函数需要简单地将匹配类型作为输入参数:std::vector<FlattenedMapWithOrder>
。
为此,C++ 代码需要知道类型 FlattenedMapWithOrder
.
为此,您需要 #include "eigency_cpp.h"
。不幸的是,这个 header 不是独立的。
因此,(感谢@ead)我添加了这些行:
#include <numpy/ndarraytypes.h>
#include <complex>
typedef ::std::complex< double > __pyx_t_double_complex;
typedef ::std::complex< float > __pyx_t_float_complex;
#include "eigency_cpp.h"
使用它,我能够在我的 C++ 代码中声明这个函数:
void MyCppFunctionVector(
const std::vector<eigency::FlattenedMap<Eigen::Matrix, float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrixList,
std::vector<eigency::FlattenedMap<Eigen::Matrix, float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& outputMatrixList
);
我的 *.pxy 文件看起来像:
cdef extern from "source_cpp_cython/cpp_source_cpp.h":
cdef void _MyCppFunctionVector "MyCppFunctionVector"(
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &,
vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] &
)
def my_python_function_vector(
list my_matrix_list_input,
list my_matrix_list_output
):
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec_input
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_input_cpp
cdef vector[FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec_output
cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_output_cpp
# Convert input matrix to C++ type.
for my_matrix_input in my_matrix_list_input:
my_matrix_input_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix_input)
matrix_map_vec_input.push_back(my_matrix_input_cpp)
for my_matrix_output in my_matrix_list_output:
my_matrix_output_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix_output)
matrix_map_vec_output.push_back(my_matrix_output_cpp)
# Call the C++ function.
_MyCppFunctionVector(matrix_map_vec_input, matrix_map_vec_output)
return my_matrix_list_output
就是这样。