我正在Linux中使用gcc 4.8.2和Python 2.7为我的自定义C++库构建python绑定。 我有以下文件夹结构我的代码Python C界面,不同模块共享静态变量?
module/
__init__.py
submodule1.so # first part of lib
submodule2.so # second part of lib
submodule3.py # additional python tools
内。在__init__.py
import submodule1, submodule2 submodule3
我需要通过对应于submodule1和submodule2之间静态类成员变量C++指针。 为此,我一直在使用capsules
。基本上在submodule1我有一个PyObject * exportCapsule()
功能和submodule2我有一个importCapsule(PyObject *)
现在,我发现我并不需要使用这些功能,我想知道为什么。 我收到John Bollinger的解释(请参阅下面的回复),关于不同的Python模块为静态类成员变量共享相同名称空间的事实。
我包一个完整的设置备案如下:
文件singleton.hpp
定义类的静态成员的单样行为::
#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
文件submodule1.cpp定义了第一模块::
//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);
}
文件submodule2.cpp
定义第二个模块::
//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
submodule1 = Extension('submodule1', sources = ['submodule1.cpp'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
ext_modules = [submodule1])
文件setup_submodule2.py
建设第二个模块::
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
文件文件setup_submodule1.py
cha的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
而且make all
输出::
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<myClass>::_ptrInstance
,而不必使用胶囊导出和导入。我怀疑它与
*.so
中的符号有关。如果我拨打nm -g *.so
,我可以看到相同的符号。我真的很惊讶,两个独立编译的模块可以共享一个变量。这是正常的吗?
我收到了一个明确的答案:这两个模块共享变量,因为名称空间对于所有模块都是通用的,而我期待着不同的名称空间。
是'template T * Singleton :: _ ptrInstance(NULL);'实际上在一个头文件中?这不应该工作。 –
QuestionC
2015-03-13 21:11:38
继您的评论后,我使用完整设置更新了该问题。您可以找到重现我的实验所需的所有文件。 – MathiasOrtner 2015-03-15 17:36:06