Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.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 C接口,不同模块共享静态变量?_Python_C++_C_Static_Shared Libraries - Fatal编程技术网

Python C接口,不同模块共享静态变量?

Python C接口,不同模块共享静态变量?,python,c++,c,static,shared-libraries,Python,C++,C,Static,Shared Libraries,我正在使用GCC 4.82和Python 2.7在Linux中为我的自定义C++ LIB构建Python绑定。 我的代码中有以下文件夹结构 module/ __init__.py submodule1.so # first part of lib submodule2.so # second part of lib submodule3.py # additional python tools 在\uuuu init\uuuuu.py中 import submodule1,

我正在使用GCC 4.82和Python 2.7在Linux中为我的自定义C++ LIB构建Python绑定。 我的代码中有以下文件夹结构

module/
  __init__.py  
  submodule1.so # first part of lib
  submodule2.so # second part of lib
  submodule3.py # additional python tools
\uuuu init\uuuuu.py中

import submodule1, submodule2 submodule3

我需要通过对应于子模块1和子模块2之间静态类成员变量的C++指针。 为此,我一直在使用

胶囊。基本上在子模块1中我有一个
PyObject*exportCapsule()
函数,在子模块2中我有一个
importCapsule(PyObject*)

现在,我发现我不需要使用这些函数,我想知道为什么。 我收到了John Bollinger的解释(参见下面的回复),关于不同Python模块共享相同的静态类成员变量名称空间这一事实

我将记录的完整设置打包如下:

文件
singleton.hpp
为类似singleton的行为定义静态类成员:

#ifndef _SINGLETON_HPP
#define _SINGLETON_HPP

// Singleton.hpp

// declaration of class
// + many more things

template<typename T>
class Singleton
{
private:
  static T * _ptrInstance;

public:
  static void setInstance(T* p) 
  {
    _ptrInstance = p;
  }

  static bool doesInstanceExist() 
  {
    bool output = not(NULL == _ptrInstance);
    return output;
  }

  static T* getInstance()
  {
    return _ptrInstance;
  }
};

// declaration of static class
template<typename T>
T * Singleton<T>::_ptrInstance(NULL);

#endif    
用于构建第一个模块的文件
setup\u submodule1.py

//submodule1.cpp

#include <Python.h>
#include "singleton.hpp"

static PyObject*errorObject;


PyObject *  exportCapsule(PyObject *dummy, PyObject *args)
{
  long * ptr = Singleton<long>::getInstance();

  const char * caps_name = "ptrInstance";
  return PyCapsule_New((void *)ptr, caps_name, NULL);
}

PyObject* setValue(PyObject* self, PyObject* args)
{
  if(not(Singleton<long>::doesInstanceExist()))
  {

    // printf("Singleton ptr %p \n",Singleton<long>::getInstance());
    // printf("Singleton is null %d \n",NULL==Singleton<long>::getInstance());
    PyErr_SetString(errorObject, "Singleton does not exist");
    return NULL;
  }


  PyObject * input;
  PyArg_ParseTuple(args, "O", &input);

  if (!PyLong_Check(input))
  {
    PyErr_SetString(errorObject, "Input should be a long integer");
    return NULL;
  }


  long * ptr = Singleton<long>::getInstance();
  *ptr = PyLong_AsLong(input);

  Py_INCREF(Py_None);
  return Py_None;
}



PyMethodDef fonctions[] = {
  {"setValue", setValue, METH_VARARGS, "set singleton value from long "},
  {"exportCapsule", exportCapsule, METH_VARARGS, "export singleton"},
  {NULL, NULL, 0, NULL}
};


PyMODINIT_FUNC initsubmodule1(void)
{

  PyObject* m = Py_InitModule("submodule1", fonctions);

  errorObject = PyErr_NewException("submodule1.Exception", NULL, NULL);

  Py_INCREF(errorObject);
  PyModule_AddObject(m, "Exception",errorObject);


  long * ptr = new long(0);
  Singleton<long>::setInstance(ptr);
}
from distutils.core import setup, Extension

submodule1 = Extension('submodule1', sources = ['submodule1.cpp'])

setup (name = 'PackageName',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [submodule1])
用于构建第二个模块的文件
setup_submodule2.py

//submodule2.cpp

#include <Python.h>
#include "singleton.hpp"

static PyObject*errorObject;


// to be checked
PyObject *  importCapsule(PyObject *dummy, PyObject *args)
{


  const char * caps_name = "ptrInstance";

  PyObject * caps;
  PyArg_ParseTuple(args, "O", &caps);

  // we should also check the name... laziness
  if (not(PyCapsule_CheckExact(caps)))
  {
    PyErr_SetString(errorObject, "Input is not a capsule");
    return NULL;
  }


  long * ptr = (long *) PyCapsule_GetPointer(caps, caps_name);

  // if we want to set the same pointer it is ok
  if (Singleton<long>::doesInstanceExist());
  {
    long * ptrPrevious = Singleton<long>::getInstance();



    if (not(ptr == ptrPrevious))
    {
      PyErr_SetString(errorObject, "You've asked for setting the global ptr with a different value");
      return NULL;
    }
    else
    {
      PyErr_SetString(errorObject, "You've asked for setting the global ptr with same value");
      return NULL;

    }
  }

  Singleton<long>::setInstance(ptr);

  Py_INCREF(Py_None);
  return Py_None;

}


PyObject* getValue(PyObject* self, PyObject* args)
{
  if (not(Singleton<long>::doesInstanceExist()))
  {
    PyErr_SetString(errorObject, "Singleton does not exist");
    return NULL;
  }

  long val = *Singleton<long>::getInstance();

  return PyLong_FromLong(val);
}


PyMethodDef fonctions[] = {
  {"getValue", getValue, METH_VARARGS, "get long from singleton value"},
  {"importCapsule", importCapsule, METH_VARARGS, "import singleton as capsule"},
  {NULL, NULL, 0, NULL}
};


PyMODINIT_FUNC initsubmodule2(void)
{

  PyObject* m = Py_InitModule("submodule2", fonctions);

  errorObject = PyErr_NewException("submodule2.Exception", NULL, NULL);

  Py_INCREF(errorObject);
  PyModule_AddObject(m, "Exception", errorObject);


}
from distutils.core import setup, Extension

submodule2 = Extension('submodule2', sources = ['submodule2.cpp'])

setup (name = 'PackageName',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [submodule2])
用于测试目的的文件
test.py

if __name__ == "__main__":

    print '----------------------------------------------'
    print 'import submodule2'
    print 'submodule2.getValue()'

    import submodule2

    try:
        submodule2.getValue()
    except Exception, e:
        print '   ## catched :', e

    print '----------------------------------------------'
    print 'import submodule1'
    print 'submodule1.setValue(1L)'

    import submodule1
    submodule1.setValue(1L)
    print 'submodule2.getValue() ->', submodule2.getValue()

    print '----------------------------------------------'
    print 'capsule = submodule1.exportCapsule()'
    print 'submodule2.importCapsule(capsule)'

    capsule = submodule1.exportCapsule()

    try:
        submodule2.importCapsule(capsule)
    except Exception, e:
        print '   ## catched :', e
文件
Makefile
用于链接所有内容:

submodule1:
  python setup_submodule1.py  build_ext --inplace

submodule2:
  python setup_submodule2.py  build_ext --inplace

test:
  python test.py

all: submodule1 submodule2 test
生成所有
输出:

python test.py
----------------------------------------------
import submodule2
submodule2.getValue()
   ## catched : Singleton does not exist
----------------------------------------------
import submodule1
submodule1.setValue(1L)
submodule2.getValue() -> 1
----------------------------------------------
capsule = submodule1.exportCapsule()
submodule2.importCapsule(capsule)
   ## catched : You've asked for setting the global ptr with same value
原来的问题是:

编译后,我有两个不同的模块
submodule1.so
submodule2.so
。 我可以进口,但我不明白的是,我的胶囊是不需要的。这两个模块共享静态变量
Singleton::\u ptrInstance
,而无需使用胶囊导出和导入

我怀疑这与
*中的符号有关。所以
。如果我调用
nm-g*.so
我可以看到相同的符号

我真的很惊讶两个独立编译的模块可以共享一个变量。这正常吗


我得到了一个明确的答案:这两个模块共享变量,因为名称空间对于所有模块都是通用的,而我期望的是不同的名称空间

> P>整个C++点>代码>静态< /COD>成员变量,它们在类的所有实例之间共享。事实上,它们不属于任何实例,而是属于类本身。它们本质上是名称空间全局变量的一种形式

“所有实例”是指整个程序中的所有实例,对于Python模块,整个程序是Python解释器(即,不是单个模块)

但是,不要将静态成员变量与静态文件范围变量混淆。它们的语义完全不同——事实上几乎相反。文件作用域变量通常具有外部链接,这意味着声明的名称引用该变量在整个程序源中出现的任何位置,但是该源被划分为多个文件。另一方面,
静态
文件范围变量具有静态链接,这意味着声明的名称仅在声明出现的编译单元中引用该变量


要点:
静态
成员变量是全局变量,而
静态
文件范围变量是局部变量。欢迎来到C++。< / P >谢谢你的快速回答。我意识到
静态
成员行为。然而,我相信不同的模块会有不同的名称空间…Is
template T*Singleton::_ptrInstance(NULL)实际在标题中?那不行。听了你的话,我用完整的设置更新了这个问题。你可以找到复制我的实验所需的所有文件。