Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从numpy.uint8数组中提取无符号字符_Python_C++_Numpy_Boost Python - Fatal编程技术网

Python 从numpy.uint8数组中提取无符号字符

Python 从numpy.uint8数组中提取无符号字符,python,c++,numpy,boost-python,Python,C++,Numpy,Boost Python,我有从python序列中提取数值的代码,它在大多数情况下运行良好,但不适用于numpy数组 当我试图提取一个无符号字符时,我会执行以下操作 unsigned char val = boost::python::extract<unsigned char>(sequence[n]); 如何在C++中成功地提取一个无符号字符?我必须为numpy类型写入/注册特殊转换器吗?我宁愿使用与其他Python序列相同的代码,也不必编写使用 PyRayAbjult*/Cuff>的特殊代码。 < P

我有从python序列中提取数值的代码,它在大多数情况下运行良好,但不适用于numpy数组

当我试图提取一个无符号字符时,我会执行以下操作

unsigned char val = boost::python::extract<unsigned char>(sequence[n]);

如何在C++中成功地提取一个无符号字符?我必须为numpy类型写入/注册特殊转换器吗?我宁愿使用与其他Python序列相同的代码,也不必编写使用<代码> PyRayAbjult*/Cuff>的特殊代码。

< P>可以从Python转换器登记一个自定义的Posith.python,它处理从NoPy数组标量转换,如 NoMPy.Unt8/Cuff> C++到C++标量,例如
无符号字符
。来自python的自定义转换器注册包含三个部分:

  • 检查
    PyObject
    是否可转换的函数。返回
    NULL
    表示
    PyObject
    无法使用已注册的转换器
  • 构造函数,它从<代码> PyObjult<代码>中构造C++类型。仅当
    converter(PyObject)
    未返回
    NULL
    时,才会调用此函数
  • 将被构造的C++类型。
从NumPy数组标量提取值需要几个NumPy C API调用:

  • 必须在将要使用NumPy C API的扩展模块的初始化过程中调用。根据扩展如何使用NumPy C API,可能需要执行其他导入要求
  • 检查
    PyObject
    是否为NumPy数组标量
  • 获取标量数组的对象。数据类型描述符对象包含有关如何解释底层字节的信息。例如,其数据成员包含对应于C类型的
  • 可用于从NumPy数组标量中提取C类型值

这是一个完整的例子,演示了使用Help类,即代码> Enable NojyPyLygRyLoad ,将特定的NUMPY数组标量登记到相应的C++类型。

#包括
#包括
#定义NPY\u否\u已弃用\u API NPY\u 1\u 7\u API\u版本
#包括
//模型函数。
///@将显式提取uint8\u t的简短实体模型函数
///来自Boost.Python对象。
boost::uint8\u t test\u generic\u uint8(boost::python::object)
{
返回boost::python::extract(object)();
}
///@brief-Mockup函数,用于uint8\u t的自动转换。
boost::uint8_t test_-specific_-uint8(boost::uint8_t value){返回值;}
///@brief Mokcup函数,用于int32\t的自动转换。
boost::int32_t test_specific_int32(boost::int32_t value){返回值;}
///@支持NumPy之间自动转换的简短转换器类型
//标量和C++类型。
模板
结构启用\u numpy\u标量\u转换器
{
启用标量转换器()
{
//在另一个应用程序中使用NumPy C API所需的NumPy调用
//扩展模块。
导入数组();
boost::python::converter::registry::push_back(
&可兑换的,
&建设,,
boost::python::type_id());
}
静态void*可转换(PyObject*对象)
{
//如果满足以下所有条件,则对象是可转换的:
//-是有效的对象。
//-是一个numpy数组标量。
//-其描述符类型与此转换器的类型匹配。
返回(
对象&&//有效
PyArray_CheckScalar(对象)&&&//Scalar
PyArray_DescrFromScalar(对象)->type_num==NumPyScalarType//Match
)
?对象//可以转换Python对象。
:NULL;
}
静态空洞构造(
PyObject*对象,
boost::python::converter::rvalue_from_python_stage1_data*data)
{
//获取转换器已分配的内存块的句柄
//用于C++类型。
名称空间python=boost::python;
typedef python::converter::rvalue_from_python_storage_type;
void*storage=reinterpret\u cast(数据)->storage.bytes;
//将数组标量类型直接提取到存储器中。
PyArray_ScalarAsCtype(对象、存储);
//设置为可转换以表示成功。
数据->可转换=存储;
}
};
BOOST_PYTHON_模块(示例)
{
名称空间python=boost::python;
//启用numpy标量转换。
启用标量转换器();
启用标量转换器();
//公开测试函数。
python::def(“test_generic_uint8”和test_generic_uint8);
python::def(“特定于测试的单元8”和特定于测试的单元8);
python::def(“特定于测试的\u int32”和特定于测试的\u int32);
}
互动使用:

导入numpy >>>导入示例 >>>断言(42==example.test\u generic\u uint8(42)) >>>断言(42==example.test\u generic\u uint8(numpy.uint8(42))) >>>断言(42==example.test\u-specific\u-uint8(42)) >>>断言(42==example.test\u-specific\u-uint8(numpy.uint8(42))) >>>断言(42==example.test\u specific\u int32(numpy.int32(42))) >>>例如,测试特定于int32(numpy.int8(42)) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 ArgumentError:中的Python参数类型 示例.特定于测试的int32(numpy.int8) 与C++签名不匹配: 测试专用的int32(int) >>>示例.测试\u通用\u uint8(numpy.int8(42)) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:没有注册转换器能够生成类型的C++值 来自此类型为numpy.int8的Python对象的未签名字符 从交互式用法中需要注意的几点:

  • Python能够从
    numpy.uint8
    int
    Python对象中提取
    Boost::uint8\u t
  • enable\u numpy\u scalar\u转换器不支持促销。例如,
    test\u specific\u int32()
    接受升级为
    TypeError: No registered converter was able to produce a C++ rvalue of type 
    unsigned char from this Python object of type numpy.uint8
    
    #include <iostream>
    #include <boost/python.hpp>
    
    #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
    
    // http://docs.scipy.org/doc/numpy/reference/c-api.array.html#importing-the-api
    #define PY_ARRAY_UNIQUE_SYMBOL printnum_cpp_module_PyArray_API
    #include <numpy/arrayobject.h>
    #include <numpy/arrayscalars.h>
    
    
    /*
     * Boost python converter for numpy scalars, e.g. numpy.uint32(123).
     * Enables automatic conversion from numpy.intXX, floatXX
     * in python to C++ char, short, int, float, etc.
     * When casting from float to int (or wide int to narrow int),
     * normal C++ casting rules apply.
     *
     * Like all boost::python converters, this enables automatic conversion for function args
     * exposed via boost::python::def(), as well as values converted via boost::python::extract<>().
     *
     * Copied from the VIGRA C++ library source code (MIT license).
     * http://ukoethe.github.io/vigra
     * https://github.com/ukoethe/vigra
     */
    template <typename ScalarType>
    struct NumpyScalarConverter
    {
        NumpyScalarConverter()
        {
            using namespace boost::python;
            converter::registry::push_back( &convertible, &construct, type_id<ScalarType>());
        }
    
        // Determine if obj_ptr is a supported numpy.number
        static void* convertible(PyObject* obj_ptr)
        {
            if (PyArray_IsScalar(obj_ptr, Float32) ||
                PyArray_IsScalar(obj_ptr, Float64) ||
                PyArray_IsScalar(obj_ptr, Int8)    ||
                PyArray_IsScalar(obj_ptr, Int16)   ||
                PyArray_IsScalar(obj_ptr, Int32)   ||
                PyArray_IsScalar(obj_ptr, Int64)   ||
                PyArray_IsScalar(obj_ptr, UInt8)   ||
                PyArray_IsScalar(obj_ptr, UInt16)  ||
                PyArray_IsScalar(obj_ptr, UInt32)  ||
                PyArray_IsScalar(obj_ptr, UInt64))
            {
                return obj_ptr;
            }
            return 0;
        }
    
        static void construct( PyObject* obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data)
        {
            using namespace boost::python;
    
            // Grab pointer to memory into which to construct the C++ scalar
            void* storage = ((converter::rvalue_from_python_storage<ScalarType>*) data)->storage.bytes;
    
            // in-place construct the new scalar value
            ScalarType * scalar = new (storage) ScalarType;
    
            if (PyArray_IsScalar(obj_ptr, Float32))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Float32);
            else if (PyArray_IsScalar(obj_ptr, Float64))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Float64);
            else if (PyArray_IsScalar(obj_ptr, Int8))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Int8);
            else if (PyArray_IsScalar(obj_ptr, Int16))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Int16);
            else if (PyArray_IsScalar(obj_ptr, Int32))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Int32);
            else if (PyArray_IsScalar(obj_ptr, Int64))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, Int64);
            else if (PyArray_IsScalar(obj_ptr, UInt8))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, UInt8);
            else if (PyArray_IsScalar(obj_ptr, UInt16))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, UInt16);
            else if (PyArray_IsScalar(obj_ptr, UInt32))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, UInt32);
            else if (PyArray_IsScalar(obj_ptr, UInt64))
                (*scalar) = PyArrayScalar_VAL(obj_ptr, UInt64);
    
            // Stash the memory chunk pointer for later use by boost.python
            data->convertible = storage;
        }
    };
    
    /*
     * A silly function to test scalar conversion.
     * The first arg tests automatic function argument conversion.
     * The second arg is used to demonstrate explicit conversion via boost::python::extract<>()
     */
    void print_number( uint32_t number, boost::python::object other_number )
    {
        using namespace boost::python;
        std::cout << "The number is: " << number << std::endl;
        std::cout << "The other number is: " << extract<int16_t>(other_number) << std::endl;
    }
    
    /*
     * Instantiate the python extension module 'printnum'.
     *
     * Example Python usage:
     *
     *     import numpy as np
     *     from printnum import print_number
     *     print_number( np.uint8(123), np.int64(-456) )
     *
     *     ## That prints the following:
     *     # The number is: 123
     *     # The other number is: -456
     */
    BOOST_PYTHON_MODULE(printnum)
    {
        using namespace boost::python;
    
        // http://docs.scipy.org/doc/numpy/reference/c-api.array.html#importing-the-api
        import_array();
    
        // Register conversion for all scalar types.
        NumpyScalarConverter<signed char>();
        NumpyScalarConverter<short>();
        NumpyScalarConverter<int>();
        NumpyScalarConverter<long>();
        NumpyScalarConverter<long long>();
        NumpyScalarConverter<unsigned char>();
        NumpyScalarConverter<unsigned short>();
        NumpyScalarConverter<unsigned int>();
        NumpyScalarConverter<unsigned long>();
        NumpyScalarConverter<unsigned long long>();
        NumpyScalarConverter<float>();
        NumpyScalarConverter<double>();
    
        // Expose our C++ function as a python function.
        def("print_number", &print_number, (arg("number"), arg("other_number")));
    }