Pybind11和全局C变量

时间:2018-02-09 15:08:30

标签: pybind11

我无法使用pybind11将全局变量从C导出到Python。问题可以从一个简单的例子中复制出来。假设我们有一个头文件(global.h),如下所示:

#ifndef GLOBAL_H
#define GLOBAL_H

extern int array[];

#endif 

数组在C文件(global.c)中定义,如下所示:

#include "global.h"

int array[] = {1, 2, 3, 4};

我想使用pybind11和以下C ++文件(pyglobal.cpp)在Python模块中导出此数组:

#include <pybind11/pybind11.h>

extern "C"
{
  #include "global.h"
}

PYBIND11_MODULE(pyglobal, m)
{
  m.attr("array") = array;
}

当我使用CMake(CMakeLists.txt)生成我的库时,一切正常:

cmake_minimum_required(VERSION 2.8.12)
project(pyglobal)

find_package(pybind11 PATHS ${PYBIND11_DIR} REQUIRED)

pybind11_add_module(pyglobal pyglobal.cpp global.c)

但是当我启动python3 shell并输入

import pyglobal

我收到以下错误消息:

  

Python 3.5.2(默认,2017年11月23日,16:37:01)   [GCC 5.4.0 20160609]在linux上   输入“帮助”,“版权”,“信用”或“许可”以获取更多信息。

     
    
      

导入pyglobal       Traceback(最近一次调用最后一次):         文件“”,第1行,in       ImportError:AttributeError:array

    
  

我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

该分配是一个非常不幸的隐式强制转换,因此不会执行您认为的操作。假设您已安装numpy,以下是公开该数组的一种方法:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

extern "C"
{
  #include "global.h"
}

PYBIND11_MODULE(pyglobal, m)
{
  auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());
  m.attr("array") = pybind11::array(dtype, {3}, {sizeof(int)}, array, nullptr);
}

如果您不知道大小,则可以使用空的基本数组和大(伪)大小。只是要确保不要以限制范围的方式迭代数组。示例:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

extern "C"
{
  #include "global.h"
}

PYBIND11_MODULE(pyglobal, m)
{
  auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());
  auto base = pybind11::array(dtype, {(unsigned)-1}, {sizeof(uintptr_t)});
  m.attr("array") = pybind11::array(dtype, {(unsigned)-1}, {sizeof(int)}, array, base);
}

可以这样使用:

>>> import pyglobal
>>> for i in range(3):
...     print(pyglobal.array[i])
... 
1
3
0
>>>

,但是例如无法打印,因为这样会在整个(unsigned)-1尺寸上进行迭代。