mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-11 14:27:09 +01:00
653 lines
20 KiB
Plaintext
653 lines
20 KiB
Plaintext
//--------------------------------------------------------------------------
|
|
// Name: wxpy_api.sip
|
|
// Purpose: The implementation of the API functions that are exported
|
|
// from the core extension module.
|
|
//
|
|
// Author: Robin Dunn
|
|
//
|
|
// Created: 19-Nov-2010
|
|
// Copyright: (c) 2010-2018 by Total Control Software
|
|
// Licence: wxWindows license
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
%ModuleHeaderCode
|
|
#include <wxPython/wxpy_api.h>
|
|
%End
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
%ModuleCode
|
|
// wxPython's API helper and utility functions
|
|
|
|
//--------------------------------------------------------------------------
|
|
// wxString conversion
|
|
|
|
// See also the wxString MappedType. This code is similar, but doesn't
|
|
// allocate a new wxString instance on the heap, is able to convert
|
|
// non-string/unicode objects to unicode, and won't raise exceptions
|
|
static wxString i_Py2wxString(PyObject* source)
|
|
{
|
|
#if wxUSE_UNICODE_WCHAR == 0
|
|
#error wxString conversion can only handle WCHAR wxStrings currently
|
|
#endif
|
|
PyErr_Clear();
|
|
PyObject* uni = source;
|
|
if (PyBytes_Check(source)) {
|
|
// if it's a string object convert it to unicode first, assumes utf-8
|
|
uni = PyUnicode_FromEncodedObject(source, "utf-8", "strict");
|
|
if (PyErr_Occurred()) {
|
|
PyErr_Clear();
|
|
return wxEmptyString;
|
|
}
|
|
}
|
|
else if (!PyUnicode_Check(source)) {
|
|
#if PY_MAJOR_VERSION >= 3
|
|
uni = PyObject_Str(source);
|
|
#else
|
|
uni = PyObject_Unicode(source);
|
|
#endif
|
|
if (PyErr_Occurred()) {
|
|
PyErr_Clear();
|
|
return wxEmptyString;
|
|
}
|
|
}
|
|
wxString target;
|
|
size_t len = PyUnicode_GET_SIZE(uni);
|
|
if (len) {
|
|
wxPyUnicode_AsWideChar(uni, wxStringBuffer(target, len), len);
|
|
}
|
|
if (!PyUnicode_Check(source))
|
|
Py_DECREF(uni); // release the temporary Unicode object we created
|
|
return target;
|
|
}
|
|
|
|
|
|
// TODO: This might be a good way to share the string conversion code here and in string.sip...
|
|
// A function to convert a Python string or unicode object to a wxString
|
|
// NOTE that it is inline so it should go in the header section
|
|
//inline wxString Py2wxString(PyObject* obj, bool setException=false, int& isErr=0) {
|
|
// wxString str;
|
|
// PyObject* uni = obj;
|
|
// if (PyBytes_Check(obj)) {
|
|
// // if it's a string object convert it to unicode first, assuming utf-8
|
|
// uni = PyUnicode_FromEncodedObject(sipPy, "utf-8", "strict");
|
|
// if (PyErr_Occurred()) {
|
|
// if (setException) {
|
|
// isErr = 1;
|
|
// }
|
|
// else {
|
|
// PyErr_Clear();
|
|
// }
|
|
// return wxEmptyString;
|
|
// }
|
|
// }
|
|
// // TODO: Coerce non-unicode types to unicode here? (Classic does)
|
|
// size_t len = PyUnicode_GET_SIZE(uni);
|
|
// if (len) {
|
|
// wxPyUnicode_AsWideChar(uni, wxStringBuffer(str, len), len);
|
|
// }
|
|
// if (obj != uni)
|
|
// Py_DECREF(uni) // release the temporary Unicode object we may have created
|
|
// return str;
|
|
//}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Wrapped object checks and converters
|
|
//
|
|
// TODO: Add some versions of these helpers that take a sipTypeDef
|
|
// instead of a name? They're accessible everywhere we need them, and
|
|
// it may be enough of an efficiency boost to make it worth it.
|
|
|
|
// Create a PyObject of the requested type from a void* and a class name.
|
|
static PyObject* i_wxPyConstructObject(void* ptr,
|
|
const wxString& className,
|
|
bool setThisOwn)
|
|
{
|
|
wxString name = className;
|
|
wxString nsDelimiter = "::";
|
|
int pos = name.Find(nsDelimiter);
|
|
if (pos != wxNOT_FOUND)
|
|
name = name.Mid(pos + nsDelimiter.Len());
|
|
|
|
const sipTypeDef* td = sipFindType(name);
|
|
if (!td)
|
|
return NULL;
|
|
PyObject* transferObj = setThisOwn ? Py_None : NULL;
|
|
return sipConvertFromType(ptr, td, transferObj);
|
|
}
|
|
|
|
|
|
// Check if a PyObject is a wrapped type
|
|
static bool i_wxPyWrappedPtr_Check(PyObject* obj)
|
|
{
|
|
return PyObject_TypeCheck(obj, sipWrapper_Type);
|
|
}
|
|
|
|
|
|
// Check if a PyObject is a specific wrapped class or subclass
|
|
static bool i_wxPyWrappedPtr_TypeCheck(PyObject* obj, const wxString& className)
|
|
{
|
|
const sipTypeDef* td = sipFindType(className);
|
|
if (!td)
|
|
return false;
|
|
return sipCanConvertToType(obj, td, SIP_NO_CONVERTORS);
|
|
}
|
|
|
|
|
|
// Convert a wrapped SIP object to its C++ pointer, ensuring that it is of the expected type
|
|
static bool i_wxPyConvertWrappedPtr(PyObject* obj, void **ptr, const wxString& className)
|
|
{
|
|
const sipTypeDef* td = sipFindType(className);
|
|
if (!td)
|
|
return false;
|
|
if (! sipCanConvertToType(obj, td, SIP_NO_CONVERTORS))
|
|
return false;
|
|
int sipIsErr = 0;
|
|
*ptr = sipConvertToType(obj, td, NULL, SIP_NO_CONVERTORS, 0, &sipIsErr);
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Deal with the GIL
|
|
|
|
// Calls from wxWindows back to Python code, or even any PyObject
|
|
// manipulations, PyDECREF's and etc. should be wrapped in calls to these functions:
|
|
static wxPyBlock_t i_wxPyBeginBlockThreads()
|
|
{
|
|
if (! Py_IsInitialized()) {
|
|
return (wxPyBlock_t)0;
|
|
}
|
|
PyGILState_STATE state = PyGILState_Ensure();
|
|
return state;
|
|
}
|
|
|
|
static void i_wxPyEndBlockThreads(wxPyBlock_t blocked)
|
|
{
|
|
if (! Py_IsInitialized()) {
|
|
return;
|
|
}
|
|
PyGILState_Release(blocked);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Commonly used helpers for converting small sequences of numbers
|
|
// TODO: Are these still needed?
|
|
|
|
// A helper for converting a 2 element sequence to a pair of integers
|
|
static bool i_wxPy2int_seq_helper(PyObject* source, int* i1, int* i2)
|
|
{
|
|
bool isFast = PyList_Check(source) || PyTuple_Check(source);
|
|
PyObject *o1, *o2;
|
|
|
|
if (!PySequence_Check(source) || PySequence_Length(source) != 2)
|
|
return false;
|
|
|
|
if (isFast) {
|
|
o1 = PySequence_Fast_GET_ITEM(source, 0);
|
|
o2 = PySequence_Fast_GET_ITEM(source, 1);
|
|
}
|
|
else {
|
|
o1 = PySequence_GetItem(source, 0);
|
|
o2 = PySequence_GetItem(source, 1);
|
|
}
|
|
|
|
*i1 = wxPyInt_AsLong(o1);
|
|
*i2 = wxPyInt_AsLong(o2);
|
|
|
|
if (! isFast) {
|
|
Py_DECREF(o1);
|
|
Py_DECREF(o2);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// A helper for converting a 4 element sequence to a set of integers
|
|
static bool i_wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4)
|
|
{
|
|
bool isFast = PyList_Check(source) || PyTuple_Check(source);
|
|
PyObject *o1, *o2, *o3, *o4;
|
|
|
|
if (!PySequence_Check(source) || PySequence_Length(source) != 4)
|
|
return false;
|
|
|
|
if (isFast) {
|
|
o1 = PySequence_Fast_GET_ITEM(source, 0);
|
|
o2 = PySequence_Fast_GET_ITEM(source, 1);
|
|
o3 = PySequence_Fast_GET_ITEM(source, 2);
|
|
o4 = PySequence_Fast_GET_ITEM(source, 3);
|
|
}
|
|
else {
|
|
o1 = PySequence_GetItem(source, 0);
|
|
o2 = PySequence_GetItem(source, 1);
|
|
o3 = PySequence_GetItem(source, 2);
|
|
o4 = PySequence_GetItem(source, 3);
|
|
}
|
|
|
|
*i1 = wxPyInt_AsLong(o1);
|
|
*i2 = wxPyInt_AsLong(o2);
|
|
*i3 = wxPyInt_AsLong(o3);
|
|
*i4 = wxPyInt_AsLong(o4);
|
|
|
|
if (! isFast) {
|
|
Py_DECREF(o1);
|
|
Py_DECREF(o2);
|
|
Py_DECREF(o3);
|
|
Py_DECREF(o4);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// wxVariant helpers
|
|
|
|
|
|
// A wxVariantData class that can hold a PyObject
|
|
class wxVariantDataPyObject : public wxPyUserDataHelper<wxVariantData>
|
|
{
|
|
public:
|
|
explicit wxVariantDataPyObject(PyObject* obj = 0)
|
|
: wxPyUserDataHelper<wxVariantData>(obj) {}
|
|
|
|
virtual bool Eq(wxVariantData& data) const;
|
|
|
|
virtual wxString GetType() const { return wxT("PyObject"); }
|
|
wxVariantData* Clone() const { return new wxVariantDataPyObject(BorrowData()); }
|
|
};
|
|
|
|
bool wxVariantDataPyObject::Eq(wxVariantData& data) const
|
|
{
|
|
wxASSERT_MSG( (data.GetType() == wxT("PyObject")),
|
|
wxT("wxVariantDataPyObject::Eq: argument mismatch") );
|
|
wxVariantDataPyObject& otherData = (wxVariantDataPyObject&) data;
|
|
|
|
wxPyThreadBlocker blocker;
|
|
return PyObject_RichCompareBool(BorrowData(), otherData.BorrowData(), Py_EQ);
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper functions for the wxVariant mapped type. For the basic types that
|
|
// wxVariant knows about we will try to store/fetch natively, otherwise we'll
|
|
// just carry the PyObject through.
|
|
//
|
|
// These functions are here in the API so they can be used by both the
|
|
// wxVariant MappedType and by other classes or types that want to add support
|
|
// for additional kinds of natively supported types (see dataview for example.)
|
|
|
|
// PyObject --> wxVariant
|
|
wxVariant i_wxVariant_in_helper(PyObject* obj)
|
|
{
|
|
wxVariant value;
|
|
|
|
PyErr_Clear();
|
|
|
|
if (PyBytes_Check(obj) || PyUnicode_Check(obj))
|
|
value = Py2wxString(obj);
|
|
|
|
else if (PyBool_Check(obj))
|
|
value = (obj == Py_True);
|
|
|
|
else if (wxPyInt_Check(obj))
|
|
value = (long)wxPyInt_AS_LONG(obj);
|
|
|
|
else if (PyLong_Check(obj))
|
|
value = (long)PyLong_AsLong(obj);
|
|
|
|
else if (PyFloat_Check(obj))
|
|
value = PyFloat_AS_DOUBLE(obj);
|
|
|
|
else if (obj == Py_None)
|
|
value.MakeNull();
|
|
|
|
else if (sipCanConvertToType(obj, sipType_wxDateTime, 0)) {
|
|
wxDateTime* ptr;
|
|
int state = 0;
|
|
int isErr = 0;
|
|
ptr = (wxDateTime*)sipConvertToType(obj, sipType_wxDateTime, NULL, 0, &state, &isErr);
|
|
if (!isErr) {
|
|
value = *ptr;
|
|
sipReleaseType(ptr, sipType_wxDateTime, state);
|
|
}
|
|
}
|
|
|
|
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxBitmap"))) {
|
|
wxBitmap* ptr;
|
|
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxBitmap"));
|
|
value << *ptr;
|
|
}
|
|
|
|
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxImage"))) {
|
|
wxImage* ptr;
|
|
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxImage"));
|
|
value << *ptr;
|
|
}
|
|
|
|
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxIcon"))) {
|
|
wxIcon* ptr;
|
|
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxIcon"));
|
|
value << *ptr;
|
|
}
|
|
|
|
else if (wxPyWrappedPtr_TypeCheck(obj, wxT("wxColour"))) {
|
|
wxColour* ptr;
|
|
wxPyConvertWrappedPtr(obj, (void**)&ptr, wxT("wxColour"));
|
|
value << *ptr;
|
|
}
|
|
|
|
else if (sipCanConvertToType(obj, sipType_wxArrayString, 0)) {
|
|
wxArrayString* ptr;
|
|
int state = 0;
|
|
int isErr = 0;
|
|
ptr = (wxArrayString*)sipConvertToType(obj, sipType_wxArrayString, NULL, 0, &state, &isErr);
|
|
if (!isErr) {
|
|
value = *ptr;
|
|
sipReleaseType(ptr, sipType_wxArrayString, state);
|
|
}
|
|
}
|
|
|
|
else {
|
|
// Just use the PyObject itself
|
|
PyErr_Clear();
|
|
value = new wxVariantDataPyObject(obj);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
// wxVariant --> PyObject
|
|
PyObject* i_wxVariant_out_helper(const wxVariant& value)
|
|
{
|
|
PyObject* obj;
|
|
|
|
if (value.IsNull()) {
|
|
obj = Py_None;
|
|
Py_INCREF(obj);
|
|
}
|
|
|
|
else if (value.IsType("string"))
|
|
obj = wx2PyString(value.GetString());
|
|
|
|
else if (value.IsType("bool"))
|
|
obj = PyBool_FromLong((long)value.GetBool());
|
|
|
|
else if (value.IsType("long"))
|
|
obj = PyLong_FromLong(value.GetLong());
|
|
|
|
else if (value.IsType("double"))
|
|
obj = PyFloat_FromDouble(value.GetDouble());
|
|
|
|
else if ( value.IsType("datetime") ) {
|
|
wxDateTime val = value.GetDateTime();
|
|
obj = wxPyConstructObject(new wxDateTime(val), "wxDateTime", true);
|
|
}
|
|
|
|
else if ( value.IsType("wxBitmap") ) {
|
|
wxBitmap val;
|
|
val << value;
|
|
obj = wxPyConstructObject(new wxBitmap(val), "wxBitmap", true);
|
|
}
|
|
|
|
else if ( value.IsType("wxImage") ) {
|
|
wxImage val;
|
|
val << value;
|
|
obj = wxPyConstructObject(new wxImage(val), "wxImage", true);
|
|
}
|
|
|
|
else if ( value.IsType("wxIcon") ) {
|
|
wxIcon val;
|
|
val << value;
|
|
obj = wxPyConstructObject(new wxIcon(val), "wxIcon", true);
|
|
}
|
|
|
|
else if ( value.IsType("wxColour") ) {
|
|
wxColour val;
|
|
val << value;
|
|
obj = wxPyConstructObject(new wxColour(val), "wxColour", true);
|
|
}
|
|
|
|
else if ( value.IsType("arrstring") ) {
|
|
wxArrayString arr = value.GetArrayString();
|
|
obj = sipConvertFromType(&arr, sipType_wxArrayString, NULL);
|
|
}
|
|
|
|
else if ( value.IsType("PyObject") ) {
|
|
wxVariantDataPyObject* data = (wxVariantDataPyObject*)value.GetData();
|
|
obj = data->GetData();
|
|
}
|
|
|
|
else {
|
|
wxString msg = "Unexpected type (\"" + value.GetType() + "\") in wxVariant.";
|
|
wxPyErr_SetString(PyExc_TypeError, msg.mb_str());
|
|
obj = NULL;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Check if the app object has been created. Raises an exception if not.
|
|
|
|
// Exception for when the wx.App hasn't been created yet
|
|
// (Initialized in wxPyCoreModuleInject)
|
|
PyObject* wxPyNoAppError = NULL;
|
|
|
|
bool i_wxPyCheckForApp(bool raiseException) {
|
|
if (wxApp::GetInstance() != NULL)
|
|
return true;
|
|
else {
|
|
if (raiseException)
|
|
PyErr_SetString(wxPyNoAppError, "The wx.App object must be created first!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Make a memory view object from a C buffer and size.
|
|
|
|
PyObject* i_wxPyMakeBuffer(void* ptr, Py_ssize_t len, bool readOnly=false) {
|
|
// GIL should already be held
|
|
if (ptr && len) {
|
|
Py_buffer view;
|
|
int flags = PyBUF_FORMAT|PyBUF_ND;
|
|
if (!readOnly)
|
|
flags |= PyBUF_WRITABLE;
|
|
PyBuffer_FillInfo(&view, NULL, ptr, len, readOnly ? 1:0, flags);
|
|
return PyMemoryView_FromBuffer(&view);
|
|
} else {
|
|
Py_INCREF(Py_None); return Py_None;
|
|
// return PyBytes_FromString(""); TODO: None or an empty string?
|
|
}
|
|
|
|
// // TODO: Consider using a sip.array object instead, like this:
|
|
// // Create a sip.array of bytes, and then convert to a memoryview which is
|
|
// // basically the same thing but is a documented built-in Python type
|
|
// int flags = 0;
|
|
// if (readOnly)
|
|
// flags |= SIP_READ_ONLY;
|
|
// PyObject* array = sipConvertToArray(ptr, "B", len, flags);
|
|
// return array;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Check if an object is suitable for conversion to various "value" types that
|
|
// can be created from a sequence of numbers, such as wx.Point, wx.Colour,
|
|
// wx.Rect, etc.
|
|
|
|
bool i_wxPyNumberSequenceCheck(PyObject* obj, int reqLength=-1) {
|
|
// Used in the various places where a sequence of numbers can be converted
|
|
// to a wx type, like wxPoint, wxSize, wxColour, etc. Returns true if the
|
|
// object is a Tuple, List or numpy Array of the proper length.
|
|
|
|
// tuples or lists are easy
|
|
bool isFast = (PyTuple_Check(obj) || PyList_Check(obj));
|
|
|
|
if (!isFast ) {
|
|
// If it's not one of those, then check for an array.
|
|
// It's probably not a good idea to do it this way, but this allows us
|
|
// to check if the object is a numpy array without requiring that
|
|
// numpy be imported even for those applications that are not using it.
|
|
if (strcmp(obj->ob_type->tp_name, "numpy.ndarray") != 0)
|
|
return false;
|
|
}
|
|
|
|
// Bail out here if the length isn't given
|
|
if (reqLength == -1)
|
|
return true;
|
|
|
|
// Now check that the length matches the expected length
|
|
if (PySequence_Length(obj) != reqLength)
|
|
return false;
|
|
|
|
// Check that each item is a number
|
|
for (int i=0; i<reqLength; i+=1) {
|
|
PyObject* item;
|
|
if (isFast)
|
|
item = PySequence_Fast_GET_ITEM(obj, i);
|
|
else
|
|
item = PySequence_ITEM(obj, i);
|
|
bool isNum = PyNumber_Check(item);
|
|
if (!isFast)
|
|
Py_DECREF(item);
|
|
if (!isNum)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Get the pointer to the C++ object out of the sipSimpleWrapper structure.
|
|
// Yes, it's super unsafe and probably stupid, but here it is...
|
|
|
|
void* i_wxPyGetCppPtr(sipSimpleWrapper* sipPyObj) {
|
|
return sipPyObj->data;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Call the PyMethod_Self API, which is not available when the Python
|
|
// limited API is activated.
|
|
|
|
inline PyObject* i_wxPyMethod_Self(PyObject* method) {
|
|
return PyMethod_Self(method);
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Cleanup and reinitialize the wxModules. This is needed because sometimes an
|
|
// Extension module will first be imported *after* the wx.App has been
|
|
// created, so the wxModules in that extension will not have been registered
|
|
// and initialized because they were not yet in memory.
|
|
|
|
void i_wxPyReinitializeModules() {
|
|
if (i_wxPyCheckForApp(false)) {
|
|
// NOTE: We are intentionally NOT calling wxModule::CleanUpModules
|
|
// here because that could clear some things that will not be reset
|
|
// when used again, leading to crashes. For example, in
|
|
// wxMSWDCImpl::DoGradientFillLinear it is saving a pointer to an API
|
|
// function in a dyn-loaded DLL. When modules are cleaned up then that
|
|
// DLL will be unloaded, leaving a dangling function pointer. We'll
|
|
// likely end up with multiple instances of some things, but that is
|
|
// better than the alternaive currently.
|
|
//wxModule::CleanUpModules();
|
|
|
|
wxModule::RegisterModules();
|
|
wxModule::InitializeModules();
|
|
|
|
// And since we're not calling CleanUpModules there is no longer any
|
|
// need to re-init the image handlers.
|
|
//wxInitAllImageHandlers();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Route the various usages of the PyDate_ APIs through our API, so we only
|
|
// have to worry about PyDateTime_IMPORT being needed in one compilation unit.
|
|
|
|
int i_wxPyDateTime_Check(PyObject *obj) {
|
|
return PyDateTime_Check(obj);
|
|
}
|
|
|
|
int i_wxPyDate_Check(PyObject *obj) {
|
|
return PyDate_Check(obj);
|
|
}
|
|
|
|
wxDateTime* i_wxPyDateTime_ToWxDateTime(PyObject *obj) {
|
|
return new wxDateTime(PyDateTime_GET_DAY(obj),
|
|
(wxDateTime::Month)(PyDateTime_GET_MONTH(obj)-1),
|
|
PyDateTime_GET_YEAR(obj),
|
|
PyDateTime_DATE_GET_HOUR(obj),
|
|
PyDateTime_DATE_GET_MINUTE(obj),
|
|
PyDateTime_DATE_GET_SECOND(obj),
|
|
PyDateTime_DATE_GET_MICROSECOND(obj)/1000); // micro to milli
|
|
}
|
|
|
|
wxDateTime* i_wxPyDate_ToWxDateTime(PyObject *obj) {
|
|
return new wxDateTime(PyDateTime_GET_DAY(obj),
|
|
(wxDateTime::Month)(PyDateTime_GET_MONTH(obj)-1),
|
|
PyDateTime_GET_YEAR(obj));
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// An instance of the API structure
|
|
static wxPyAPI API = {
|
|
i_Py2wxString,
|
|
i_wxPyConstructObject,
|
|
i_wxPyBeginBlockThreads,
|
|
i_wxPyEndBlockThreads,
|
|
i_wxPyWrappedPtr_Check,
|
|
i_wxPyConvertWrappedPtr,
|
|
i_wxPy2int_seq_helper,
|
|
i_wxPy4int_seq_helper,
|
|
i_wxPyWrappedPtr_TypeCheck,
|
|
i_wxVariant_in_helper,
|
|
i_wxVariant_out_helper,
|
|
i_wxPyCheckForApp,
|
|
i_wxPyMakeBuffer,
|
|
i_wxPyNumberSequenceCheck,
|
|
i_wxPyGetCppPtr,
|
|
i_wxPyMethod_Self,
|
|
i_wxPyReinitializeModules,
|
|
i_wxPyDateTime_Check,
|
|
i_wxPyDate_Check,
|
|
i_wxPyDateTime_ToWxDateTime,
|
|
i_wxPyDate_ToWxDateTime
|
|
};
|
|
%End
|
|
|
|
|
|
%ModuleHeaderCode
|
|
#include <datetime.h>
|
|
%End
|
|
|
|
%InitialisationCode
|
|
PyDateTime_IMPORT;
|
|
%End
|
|
|
|
|
|
|
|
%PostInitialisationCode
|
|
// Code that will run when _core is imported that will stash away a
|
|
// pointer to the API structure.
|
|
PyObject* wxmod = PyImport_ImportModule("wx");
|
|
PyObject* wxmodDict = PyModule_GetDict(wxmod);
|
|
PyObject* apiObj = PyCapsule_New(&API, "wx._wxPyAPI", NULL);
|
|
PyDict_SetItemString(wxmodDict, "_wxPyAPI", apiObj);
|
|
|
|
Py_XDECREF(apiObj);
|
|
Py_DECREF(wxmod);
|
|
wxPyGetAPIPtr();
|
|
%End
|
|
|
|
//--------------------------------------------------------------------------
|