首页 > 解决方案 > Python 扩展对象和 wx 自定义事件初始化

问题描述

我有以下情况:

  1. 用 C++/Wxwidgets 2.8 和嵌入式 python 解释器编写的应用程序。
  2. 作为共享对象的 python 扩展。

这两个组件共享一些 wxwidgets 自定义事件,如下所示

DEFINE_LOCAL_EVENT_TYPE(ID_PRE_PROCESS_X_COMMAND);
DEFINE_LOCAL_EVENT_TYPE(ID_POST_PROCESS_X_COMMAND);
DEFINE_LOCAL_EVENT_TYPE(ID_PRE_PROCESS_Y_COMMAND);
DEFINE_LOCAL_EVENT_TYPE(ID_POST_PROCESS_Y_COMMAND);

我启动应用程序,然后导入扩展模块,在导入模块后,这些事件类型将更新为具有更新的 ID。

例子 :

  1. 使用 ID_PRE_PROCESS_X_COMMAND = 10304 启动的应用程序
  2. 导入 python 扩展模块,更新 ID_PRE_PROCESS_X_COMMAND = 10308

这是 ID_PRE_PROCESS_X_COMMAND 上 GDB 中观察点的输出

#0  __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at Runner.cpp:8
#1  0x00007fffe1ad02d9 in global constructors keyed to Runner.cpp(void) () at Runner.cpp:73
#2  0x00007fffe1b91fe6 in __do_global_ctors_aux () from /path/to/Dependcy.so    
#3  0x00007fffe1aacb23 in _init () from /path/to/Dependcy.so
#4  0x00007fffe1df8888 in ?? () from /path/to/ExtensionModule.so
#5  0x00007ffff7deb1e8 in call_init () from /lib64/ld-linux-x86-64.so.2
#6  0x00007ffff7deb317 in _dl_init_internal () from /lib64/ld-linux-x86-64.so.2
#7  0x00007ffff7def636 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#8  0x00007ffff7deae76 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#9  0x00007ffff7deee2b in _dl_open () from /lib64/ld-linux-x86-64.so.2
#10 0x00007ffff6017f9b in dlopen_doit () from /lib64/libdl.so.2
#11 0x00007ffff7deae76 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#12 0x00007ffff601833c in _dlerror_run () from /lib64/libdl.so.2
#13 0x00007ffff6017f01 in dlopen@@GLIBC_2.2.5 () from /lib64/libdl.so.2
#14 0x00007ffff6571064 in _PyImport_GetDynLoadFunc (fqname=<optimized out>, shortname=0x7fffe4085d50 "ExtensionModule", 
    pathname=0x7fffe4086d60 "/path/to/ExtensionModule.so", fp=0x7fffe40374a0) at Python/dynload_shlib.c:130

问题是如何防止这些事件的多次初始化,以便即使在加载扩展模块之后它们的数量也是恒定的。


编辑 1

经过一些调试后,我发现它DEFINE_LOCAL_EVENT_TYPE(ID_PRE_PROCESS_X_COMMAND);被扩展到const wxEventType ID_PRE_PROCESS_X_COMMAND = wxNewEventType()

wxNewEventTypewxWdigets 中定义如下

int wxNewEventType()
{
    // MT-FIXME
    static int s_lastUsedEventType = wxEVT_FIRST; // wxEvt_FIRST = 10000

    return s_lastUsedEventType++;
}

由于在共享对象和主应用程序中使用 Runner.cpp 作为翻译单元,它的全局构造函数被调用两次,导致 wxNewEventType 被调用两次,从而改变了 Event Types 的值。

我不确定是否有办法防止这种情况发生,或者我会尝试将事件转移到其他地方。

标签: pythonc++shared-librarieswxwidgets

解决方案


推荐阅读