[wx-dev] IPC issues
Brian Vanderburg II
BrianVanderburg2 at aim.com
Sat Dec 1 17:03:51 PST 2007
Vadim Zeitlin wrote:
> On Sat, 01 Dec 2007 09:38:39 -0500 Brian Vanderburg II <BrianVanderburg2@=
aim.com> wrote:
>
> BVI> wxString GetDataAsText(const void* data, size_t size, wxIPCFormat fo=
rmat)
> BVI> {
> BVI> assert(format is valid)
> BVI> =
> BVI> #if wxUSE_DDE_FOR_IPC
> BVI> // the received data in GetDdeData is always in the format th=
e =
> BVI> program is in
> BVI> wxUnusedVar(format)
> BVI> #if wxUSE_UNICODE
> BVI> return wxString((wchar_t*)data, size);
> BVI> #else
> BVI> return wxString((char*)data, size);
> BVI> #endif
> BVI> #else
> BVI> if(format =3D=3D wxIPC_TEXT)
> BVI> return wxString((char*)data, wxConvLibc);
> BVI> else if(format =3D=3D wxIPC_UTF8TEXT)
> BVI> return wxString((char*)data, wxConvUTF8);
> BVI> else
> BVI> return wxString((wchar_t*)data);
> BVI> #endif
> BVI> }
>
> In fact thinking more about it (and looking at the code) it seems that it
> should be enough to set the format for DDE correctly, shouldn't it? So I'm
> afraid I'm back to not understanding why exactly doesn't this work
> currently, could you please reexplain? Thanks!
> =
The code that was patched last makes it where DDE will send in the =
correct format when doing DdeClientTransaction and when receiving, it =
will call OnExecute passing the correct format based on the build. But =
still, the code in MyConnection::OnExecute can't reliably do if(format =
!=3D wxIPC_TEXT) return false, this is because with DDE in a unicode =
build, it is wxIPC_UNICODETEXT, and in ANSI it is wxIPC_TEXT. Also =
there is the fact that the OnExecute may not be for DDE but for TCP (if =
the user derived from wxConnection instead of directly from =
wxDDEConnection) and here the format is sent as-is (no behind-the-scenes =
conversion the way Windows does with DDE), GetTextFromData takes care =
of all of that automatically.
Actually, now that OnExecute does get the correct format in DDE, the =
code above does not need the #if wxUSE_DDE_FOR_IPC conditional at all. =
The function simply serves to simplify code so one can do this:
bool MyConnection::OnExecute(const wxString& topic, const void* data, =
size_t size, wxIPCFormat format)
{
....
wxString txt =3D GetTextFromData(data, size, format);
}
Where one may normally have to do this:
bool MyConnection::OnExecute(...)
{ =
if(format =3D=3D wxIPC_TEXT) // ANSI text (maybe ANSI compiled =
application using DDE or could also be TCPConnection and the client used =
wxIPC_TEXT
{
}
else if(format =3D=3D wxIPC_UNICODETEXT) // Unicode compiled applicatio=
n =
using DDE, or TCP connection and client used wxIPC_UNICODETEXT
{
}
else if(format =3D=3D wxIPC_UTF8TEXT)
{
// Sending application sent as wxIPC_UTF8TEXT
}
}
wxDDEConnection::OnExecute will get data as wxIPC_TEXT in ansi and =
wxIPC_UNICODE_TEXT in unicode build
wxTCPConnection::OnExecute will get data in the format that it was sent =
as from the client, regardless of the build.
So for a derived connection class to be as portable as possible, without =
conditionals for testing, GetTextFromData can be used.
And it will work whether it is a DDE or TCP connection.
If it is wxDDEConnection, then format will always be wxIPC_UNICODETEXT =
in unicode and wxIPC_TEXT in ansi and the function will convert it =
accordingly. If it is wxTCPConnection, it is possible to send any =
format since it is sent as is. A client application built in unicode =
can do: Execute("Some action", size of some action), and it will be sent =
as wxIPC_TEXT and the server will get wxIPC_TEXT even it it is build in =
unicode, can use GetTextFromData still to convert it to wxString
> BVI> There is a minor problem with this code. If an empty string is sent =
> BVI> then the return string IsEmpty should be true, but the size will inc=
lude =
> BVI> the null terminator and so wxString(data, size) will have the extra
> BVI> null that it should not have. =
>
> I don't understand this at all: size of empty string is 0 and wxString
> ctor from 0 length should create empty string. Do you say there is a bug =
in
> wxString here?
> =
No it's not a bug. When I do Execute("ABC"), it does strlen(data) + 1, =
which is 3 + 1 =3D 4. Now when receiving it, wxString(data, size), will =
tell it that the size is 4, and will include the null terminator. =
Simillarly, if I do Execute(""), it does strlen(data) + 1 =3D 0 + 1 =3D 1, =
so the if the server connection does wxString s(data, size), size will =
be 1 so the string will include the null terminator as part of the =
string (an embedded null), and so s.IsEmpty() will return false.
=
I've attached a 'partial' patch of GetTextFromData
Brian Vanderburg II
-------------- next part --------------
Index: include/wx/ipcbase.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- include/wx/ipcbase.h (revision 50401)
+++ include/wx/ipcbase.h (working copy)
@@ -166,6 +166,9 @@
virtual bool OnDisconnect() { delete this; return true; }
=
=
+ // Convert passed data to a string
+ wxString GetTextFromData(const void* data, size_t size, wxIPCFormat form=
at);
+
// return a buffer at least this size, reallocating buffer if needed
// returns NULL if using an inadequate user buffer which can't be resized
void *GetBufferAtLeast(size_t bytes);
Index: src/common/ipcbase.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- src/common/ipcbase.cpp (revision 50401)
+++ src/common/ipcbase.cpp (working copy)
@@ -65,6 +65,43 @@
delete m_buffer;
}
=
+// The calls to Execute/Poke/Etc can automatically specify the format.
+// This function makes it so the callbacks can automatically get the
+// string without a bunch of if(format =3D=3D ...) else if(format =3D=3D .=
..)
+wxString wxConnectionBase::GetTextFromData(const void* data, size_t size, =
wxIPCFormat format)
+{
+ wxCHECK_MSG(format =3D=3D wxIPC_TEXT || format =3D=3D wxIPC_UNICODETEX=
T || format =3D=3D wxIPC_UTF8TEXT,
+ wxEmptyString, "wxConnectionBase::GetTextFromData() only suppo=
rted text formats.");
+
+ if(size =3D=3D 0)
+ return wxEmptyString;
+
+ // A small helper
+ #define GTFD_FixSize(fmt, str, len) \
+ { \
+ len /=3D sizeof(fmt); \
+ while(len > 0 && ((fmt*)str)[len - 1] =3D=3D 0) \
+ len--; \
+ }
+
+#if wxUSE_UNICODE_UTF8
+ if(format =3D=3D wxIPC_TEXT || format =3D=3D wxIPC_UTF8TEXT)
+ {
+ GTFD_FixSize(char, data, size);
+ return wxString((char*)data, size);
+ }
+ else
+ {
+ GTFD_FixSize(w_chart, data, size);
+ return wxString((wchar_t*)data, size);
+ }
+#elif wxUSE_UNICODE
+
+#else
+
+#endif
+}
+
void *wxConnectionBase::GetBufferAtLeast( size_t bytes )
{
if ( m_buffersize >=3D bytes )
More information about the wx-dev
mailing list