我正在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