← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3162: allow DWT to be used in a shared library

 

------------------------------------------------------------
revno: 3162
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2012-12-27 14:37:10 +0100
message:
  allow DWT to be used in a shared library
added:
  dwt/Preprocessor macros.txt
modified:
  dwt/include/dwt/Application.h
  dwt/src/Application.cpp
  dwt/src/Dispatcher.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== added file 'dwt/Preprocessor macros.txt'
--- dwt/Preprocessor macros.txt	1970-01-01 00:00:00 +0000
+++ dwt/Preprocessor macros.txt	2012-12-27 13:37:10 +0000
@@ -0,0 +1,20 @@
+This document lists preprocessor macros available to tweak the way DWT is built.
+
+--- Important ---
+
+DWT_SHARED: Define when DWT is meant to be used in a shared library, rather than in a main
+application.
+When DWT_SHARED is defined, the implementor is expected to call dwt::Application::init
+and dwt::Application::uninit. It is assumed the host of the library will be pumping messages; so no
+message loop is provided under DWT_SHARED.
+When DWT_SHARED is not defined, the implementor is expected to provide the dwtMain function which
+DWT calls and which should launch the message loop by calling dwt::Application::run.
+Note that a few features of DWT have limited availability under DWT_SHARED; notably:
+- Asynchronous calls (set by dwt::Application::callAsync or dwt::Widget::callAsync) are synchronous
+(because the shared library can't inject its asynchronous calls into its host's message pump).
+- Accelerator keys aren't handled (for similar reasons).
+
+--- Debugging ---
+
+DWT_DEBUG_WIDGETS: Define to write debugging messages to standard output whenever a widget is
+created or destroyed. This is useful to track widget leaks.

=== modified file 'dwt/include/dwt/Application.h'
--- dwt/include/dwt/Application.h	2012-09-21 18:35:34 +0000
+++ dwt/include/dwt/Application.h	2012-12-27 13:37:10 +0000
@@ -74,7 +74,9 @@
   */
 class Application :public boost::noncopyable
 {
+#ifndef DWT_SHARED
 	static int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
+#endif
 
 	friend class Widget;
 public:
@@ -139,7 +141,7 @@
 	/// The initialization that must be done first.
 	/** Used internally by the WinMain function, and externally for DLL initialization.
 	  */
-	static void init( int nCmdShow );
+	static void init();
 
 	/// Shut down operations
 	static void uninit();
@@ -152,6 +154,7 @@
 	const CommandLine & getCommandLine() const;
 
 	int getCmdShow() const;
+	void setCmdShow(int cmdShow);
 
 	/// Adds a waitable event HANDLE and the according signal
 	/** You can feed in here HANDLEs of thread handles, console inputs, mutexes,
@@ -198,7 +201,7 @@
 	DWORD threadId;
 
 	// Private Constructor to ensure Singleton Implementation
-	Application( int nCmdShow );
+	Application();
 
 	~Application();
 

=== modified file 'dwt/src/Application.cpp'
--- dwt/src/Application.cpp	2012-12-21 22:50:48 +0000
+++ dwt/src/Application.cpp	2012-12-27 13:37:10 +0000
@@ -41,8 +41,6 @@
 #include <dwt/widgets/Control.h>
 #include <assert.h>
 
-extern int dwtMain(dwt::Application& app);
-
 namespace dwt {
 
 Application* Application::itsInstance = 0;
@@ -53,8 +51,8 @@
 /** Initializes the runtime for SmartWin++
  Typically only called by WinMain or DllMain.
  */
-void Application::init(int nCmdShow) {
-	itsInstance = new Application(nCmdShow);
+void Application::init() {
+	itsInstance = new Application();
 
 	BOOL enable;
 	if(::SystemParametersInfo(SPI_GETUIEFFECTS, 0, &enable, 0) && !enable) {
@@ -73,8 +71,8 @@
 	::InitCommonControlsEx(&init);
 }
 
-Application::Application(int nCmdShow) :
-	itsCmdShow(nCmdShow),
+Application::Application() :
+	itsCmdShow(0),
 	tasks(1024),
 	quit(false),
 	threadId(::GetCurrentThreadId())
@@ -223,6 +221,10 @@
 	return itsCmdShow;
 }
 
+void Application::setCmdShow(int cmdShow) {
+	itsCmdShow = cmdShow;
+}
+
 bool Application::dispatchAsync() {
 	Callback callback;
 	if(tasks.pop(callback)) {
@@ -232,11 +234,22 @@
 	return false;
 }
 
+#ifndef DWT_SHARED
+
 void Application::callAsync(const Callback& callback) {
 	tasks.push(callback);
 	wake();
 }
 
+#else
+
+// async calls don't work when we aren't in charge of the message loop - run them synchronously.
+void Application::callAsync(const Callback& callback) {
+	callback();
+}
+
+#endif
+
 Application::FilterIter Application::addFilter(const FilterFunction& f) {
 	return filters.insert(filters.end(), f);
 }
@@ -247,13 +260,19 @@
 
 } // namespace dwt
 
+#ifndef DWT_SHARED
+
+extern int dwtMain(dwt::Application& app);
+
 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
-	dwt::Application::init(nCmdShow);
+	dwt::Application::init();
 
 	auto hr = ::OleInitialize(nullptr);
 	if(FAILED(hr))
 		return hr;
 
+	dwt::Application::instance().setCmdShow(nCmdShow);
+
 	int ret = dwtMain(dwt::Application::instance()); // Call library user's startup function.
 
 	::OleUninitialize();
@@ -262,3 +281,5 @@
 
 	return ret;
 }
+
+#endif

=== modified file 'dwt/src/Dispatcher.cpp'
--- dwt/src/Dispatcher.cpp	2012-11-05 20:39:11 +0000
+++ dwt/src/Dispatcher.cpp	2012-12-27 13:37:10 +0000
@@ -220,7 +220,13 @@
 	std::basic_stringstream<TCHAR> stream;
 	stream << name.c_str();
 
-	classNames.push_back(stream.str());
+#ifdef DWT_SHARED
+	/* in a shared library, classes registered by the lib can't clash with those regged by the host
+	or by other dynamically loaded libs. append a (hopefully unique) string to that end... */
+	stream << &Application::instance();
+#endif
+
+	classNames.push_back(move(stream.str()));
 	return classNames.back().c_str();
 }