I've investigated some issues since Lorenzo raised some important questions this afternoon. I sum up everything here :
1) All class declarations will have the 'NGL_API' prepended. There are currently exactly 30 public classes in NGL. We don't have standalone functions. More on the only App and UserApp globals further. 2) NGL_API is an empty macro as a default, ie. we have this in ngl_config.h : #ifndef NGL_API #define NGL_API #endif 3) If NGL_USE_DLL and _WIN32_ are defined, then we do the required magic for Windows : - to use NGL as a dll, the user will add this macro in his project settings. NGL_API becomes '__declspec(dllimport)' as required - the libngl_dll.dsp projects has a 'NGL_BUILD_DLL' in its preprocessor global macros, and NGL_API becomes '__declspec(dllexport)' in order the built DLL exports the symbols. This is actually not mandatory, as the standard '_DLL' macro from MSVC (added by the wizard) is also detected. 4) I checked that every process has its own copy of the DLL data segment, both under Linux and Windows. It means that when the DLL code accesses the App global, it is the one of the current process context. It was not extremely clear from the MSDN docs, and I had some doubts on the Unix's ld defaults. http://msdn.microsoft.com/library/en-us/dllproc/dll_92sh.asp Funny note: we (Lorenzo and I) first believed that the DLL's data was globally unique and that we would have to change App into a map<PID, nglApplication*> lookup. I even benched getpid() on my machine to see if it was acceptable : 400 clock cycles (2Mop/s on my 800Mhz). Would have fit :). It turns out that Unix ld's has a special data section for globally unique symbols, and Windows requires the explicit use of shared memory. Relief. BTW, important read for DLL users : http://msdn.microsoft.com/library/en-us/dllproc/dll_2jqf.asp 5) I checked that this necessary trick is OK with GCC and MSVC : nglApplication& App = *(nglApplication*)0; No warning. C++ is l33t. 6) Now about our two globals App and UserApp : - App resides in the DLL's data segment, is init'ed to 0 when the DLL is runtime-lodaded with the ugly trick shown above, and is exported - UserApp resides in the user's EXE data segment. It is inited last (after all DLLs implicit loading, ngl.dll being amongst them) by the static user's class constructor. It should execute this ASAP (first line of constructor) : App = *this; 7) All this will be done with successive patches. I've already most of the job done on my local repository. The rule is : first, don't affect the static version. Then try to make the DLL build work. -- The nice thing about all this, it's that I realized how we tied things together around the application class. There are basically two sorts of dependencies : - Logging : most classes can talk. This is a very nice and configurable feature (did I already told you that ? :)). Currently warning and error levels are still compiled in in release mode. We could easily change this to completely disable logging in NGL, but it would require a supplemental macro (because we can't use multiple-args macro and mute LOG/OUT easily). Boring text editing, not worth the trouble for now. But will be done someday, I expect users will ask for this feature. Then I'll say 'nice idea, send me a patch' :). - Global ressources : most of them are caches. nglFont has global caches through static variables. This prevents the user from explicitly building a nglFontManager and passing it to every nglFont constructor, however this could be done without great hassle (you don't build nglFont objects all the time). More troublesome are things like nglStringConv under Win32 where we cache the MLang COM object factory. While nglStringConv is mostly used in NGL internals, users are expected to rely on high level services like streams for encoding conversions. And we wouldn't like people to pass an 'encoding conversion context' to stream objects ... Last thing about DLL support : I think that the concept is valuable if used systematically. Thus I'm also working on DLL builds of libpng, libjpg, STLport and so on. This is boring since most of the time this is not available nor maintained, but fortunately (and very sadly for my mental health) building those DLLs is part of my current job. Received: from zerodeux.net ([62.212.104.175]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17bBlk-00047W-00 for <[EMAIL PROTECTED]>; Sat, 03 Aug 2002 20:09:24 -0700 Received: from localhost.localdomain (zerodeux.home [192.168.1.3]) by zerodeux.net (Postfix) with ESMTP id C2FDDB3CC for <[EMAIL PROTECTED]>; Sun, 4 Aug 2002 05:09:24 +0200 (CEST) From: Vincent Caron <[EMAIL PROTECTED]> To: NGL devel ML <[EMAIL PROTECTED]> Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.7 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 Subject: [NGL-devel] Font status Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sat Aug 3 20:10:02 2002 X-Original-Date: 04 Aug 2002 05:09:12 +0200 The new nglFont code is close to be functionnal. The nglFontBase code currently in CVS is ~2000 lines. The upcoming nglFont class will only manage texture caching and rendering, reuse most of the current code for this purpose, and hardly be above 800 lines. There is already a new examples/font/info demo which tests nglFontBase services. Examples/font/metrics is currently being rewritten to reflect the more sophisticated (and correct!) metrics and rendering services. nglFontBase/nglFont already do a lot of things. It uses a wealth of FreeType's available caches and methods, manage for missing charmaps (encoding conversion on the fly) and compute layouts. The plan is to keep nglFont to this level and not overstuff it : - loading a font from a file (or a stream) - requesting metrics - provide an efficient framework for text layout and rendering As Meeloo notified me yesterday, this is not sufficient for a UI toolkit. Here are the services that nglFont shouldn't support (but will provide means to support them). First part : what we should solve. Second part : how NUI would solve it. First part ---------- * Font ressource caching and naming. Yes, this is tied. FreeType provides a 'face object' cache. All you have to do is provide him with a callback that maps a font ressource name to a globally unique ID (let's say GUID :)). The current nglFontBase face cache relies on the font's absolute path : the GUID is actually a pointer to an object holding this information (_nglInstalledFont). This should work great for most users, as we don't expect people to move their font files around while their application is running, unless it's a font browser :) From a UI tookit point of view, this is not sufficient. A toolkit doesn't have to guess where the font files are, nor that the bold italic variation of arial is 'arialbi.ttf'. I see two levels of abstraction : - the classical : * face name (arial, courier, helvetica, ...) * slant (regular, italic) * weight (regular, bold) * size We manage to map these description to actual file names. Most of the time we need to scan font folders for that purpose. We expect to add the OS font's path when possible. Any path specified in '~/.nglrc'. The <application_path>/fonts folder. The current theme path. And so on. - the high level : * family (mono, serif, sans) * slant * weight * size Seems also the same ... But in this case we only ask for the three canonical font families. The idea is that a theme should set its look'n'feel by defining the exact font names for each of theses 3 families. 'Mono' is a monospaced font (usually Courier) suitable for plaintext, coding, etc. 'Sans' (ie. sans serif) is the 'default' font for most interfaces (Arial, Tahoma, Helvetica). 'Serif' is the 'document' font, suitable for wysywyg or such (this is what is mostly used on paper : Schoolbook, Times). BTW, a serif is this little perpendicular segment which terminates unclosed font outlines. I didn't know this before I entered FreeType's doc ... This clutters legibility on low resolution devices (a screen ! 10-15 pixels are barely enough to display comfortable outlines), while it enhances it on high resolution devices (paper @ 300-600dpi). This is both a technical and human perception issue. 'Size' is part of a font ressource description, in order to fetch bitmap fonts. The Unix world still uses huge banks of bitmap fonts. Japanese and Chinese people still often prefer finely tuned bitmap fonts for their complex and rich symbols. And it's actually impossible to properly hint Kanji characters at small pixel sizes for instance, vectorial versions are for printing. Now we see TrueType asiatic fonts with 'embedded' bitmaps : these are pre-rendered and hand-tuned bitmaps at given sizes. nglFontBase fetches such bitmaps if available at the current size, and falls back to regular outline rendering otherwise. * Glyph caching The current strategy is to hold one glyph cache per nglFont instance. To be more precise, there are two glyph caches : - a generic global glyph cache which fits everything (outlines, bitmaps, any size, any font). This is rather space efficient and speeds up raw loading and rendering of glyphs. This is transparent to both nglFont user and implementor (this is a nglFontBase internal feature) - a renderer specific cache, this is a texture for nglFont. This is currently tied to the couple {font, size}. One texture cache per font object at a given size. If you change a nglFont size, this will invalidate the cache (it will be automatically and transparently resized and refilled by subsequent rendering operations). The job of the toolkit is to manage those caches. To sum up we have to keep a collection of nglFont objects where each object maps to a given {font GUID, size} couple. * Glyph rendering Now you should have noticed that regular, bold, italic and bold+italic glyphs are not the same. The fact is that it is not possible to produce a 'reasonable' bold version of a font by simple computing, so this is a whole different and hand-designed font ressource. The same applies for italic style, however it is somewhat possible to produce an automatic slant with a shearing transformation. This is easily done by FreeType (it accepts any input transformation matrix), but hinting and grid-fitting fails and the result at small pixel sizes is awful. Last thing, which is not part of glyph rendering : overstrike and underlining. This is actually part of the layout rendering : you cannot do proper underlining if you don't consider a whole string. Well, some people reported doing so (ie. rendering underlines directly in their glyph bitmaps and hopping everything connects in a string), but had virtually no real layout support. Other detail : such a thing does not need caching, drawing a line is a primitive in any graphics API. This why you don't have such a thing like underline or overstrike flags in nglFontBase, but expect it in the (upcoming) nglFont. Part 2 ------ First, font description : my guess is that we should provide a mean to use any access level. - 1 : file://font.ttf - 2 : {font name, slant, weight, size} - 3 : {family name (, slant, weight, size)} The third level should also provide default {slant, weight, size}. This is expected to be Theme data : a theme provides a consistent look by choosing both fonts and slant/weight/sizes. nglFont objects maps to the {font name, slant, weight} triplet. The cache management should holds collection of nglFont copies for different sizes. All of this can be easily done by providing this maping : "absolute/font/path:size" -> GUID. However this would be brute force and insufficient. We can't systematically allocate a texture cache for every size of a font the user requests. We should have a LRU queue (Least Recently Used) to keep a restricted set of most used caches. And we should have a priority feature : we obviously would like to favor thje theme's default fonts (full spec including size) over its variants. So we should provide the following services : - register font path - map {name, slant, weight, size} to a nglFont object - map {family (, slant, weight, size)} to a nglFont object (theme dependent) - assign a cache priority to a nglFont object I don't know how to handle the dependency with the theme. I expect this should actually be part of the Theme services : a theme could return any class based on nglFontBase (nglFont being the 2D default renderer). We also expect theme descriptions to provide their fontset (ie. add a path to its font file collection, defines the high-level 'family' mapping, assign high cache priority to the default fonts, etc). In any event this should lead to a nuiFont class : this is what NUI users should manipulate if they want to set a specific font on a widget. Most of the time this will be something like changing the weight, slant or size of a default theme font, so this should be easy to achieve. We also have to solve the layout pb. A proper layout method need the described higl-level services to work : imagine an HTML page, you need to fetch a bunch of different fonts from simple descriptions (underlined, bold, smaller, exposant/indice, etc). This should be a per-widget pb. Note that nglFontBase layout code is sufficient for simple labels (ie. renders newlines). -- Side note : we could reasonably use the HTML style where the user can provide a list of font names, and the application tries to match them with the available system fonts in the given order. Ie. "arial, helvetica" will mostly match the Helvetica font on Unix and Mac platforms. A theme can also provide its font set as part of its data. It's hard to find good and free scalable screen fonts. Scalable fonts are very hard to correctly hint at small sizes, and only a few famous foundry (Adobe, Mototype/Agfa, Linotype, Porchez, Bigelow & Holmes, etc) can achieve this. These are all commercial fonts. The most complete free font collection is the URW++ one (a foundry in Germany), donated to the Ghostscript project and under the GPL. They include mono, sans and serif with italic and bold variants. Helas, they have poor/incomplete hinting at small sizes (they were targeted to 600dpi devices !), but they improve slowly thanks to some sparse developers who know the art of hinting. I guess we could use this font collection to build a 'standalone and portable theme' at one time. http://freesoftware.fsf.org/download/freefont/freefont-ttf.zip Last one : the huge collections of TrueType fonts found on the web holds about 95% of fantasy fonts (ie. not really suitable for every day work and mail reading :)), and what's wore 99,9% of them are not hinted. It means that they are rarely legible under 20 or 30 pixels. They also have no kerning info. I gave up finding a 'cool' font in those collections, it hurts the NUI demo. Received: from meeloo.net ([62.4.18.112]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17iSrF-0004wy-00 for <[EMAIL PROTECTED]>; Fri, 23 Aug 2002 21:49:09 -0700 Received: from harry ([10.1.1.4]) by meeloo.net with smtp (Exim 3.35 #1 (Debian)) id 17iSr1-0003S6-00 for <[EMAIL PROTECTED]>; Sat, 24 Aug 2002 06:48:55 +0200 Message-ID: <[EMAIL PROTECTED]> From: "Sebastien Metrot" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2600.0000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Subject: [NGL-devel] ngl design concerning nglApplication (loonnng...) Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Fri Aug 23 21:50:01 2002 X-Original-Date: Sat, 24 Aug 2002 06:47:17 +0200 Hi all! I have been having a very insightful discution with Lorenzo tonight, on the subject of the design of ngl. The main subject was the dll support issue (as usual now ;) and some very related design issues in nglApplication/nglApplicationBase. I'll try to sumarize the main ideas that we exchanged tonight in this mail. First we can say there is a bit of a convergence concerning the needs of a libngl.dll target lately. [nice hyperbolea to say I kinda changed my mind ;-P]. For different reasons altogether, Vincent, Lorenzo and even I do feel it will help solve some issues about application design (I also feel that doing the work needed to create the target correctly will probably create a bunch of quirks here and there). -Vincent needs it to please his linux friends as he allready exaplained to us :-P. -Lorenzo needs it because the application he is working on needs to have a "kernel" dll that is shared by many apps and that these apps may have to load other dlls. -I need it for my job at IVS to be able to create an extensible and strealined video capture system where ngl aware video "drivers" (dlls...) will be loaded in ngl aware and ngl unaware hosts. I also need it to strengthen the ngl/nui vst plugin targets (I have some nifty cases concerning this last bit like multithreading issues and other calamities that we don't support at all for the moment). After toying a bit with the idea (and while implementing two simple vstplugin samples and the most part of the video driver system) I encoutered the main problem of the current ngl design: the creator of the nglApplicationXXX instance is not fixed. It can be an application (exe) or a dll (a vst plugin, a video driver, etc...). In the simplest cases this is not a problem: if we just have an application it just has to create the object. If there is one vst plugin loading in cubase or logic audio it can also create the object at load time. But there are more complicated scenarii, for exemple what should happen when loading multiple ngl aware vst plugins in the same process? Which one should be responsible for creating and destroying the nglApplication instance? And what must happen if the plugins are loaded in an ngl application? How can a plugin detect if a valid nglApplication object has been created or not? Worse: if a plugin creates the instance, and then the host loads another plugin, the second one will use the allready existing instance of nglApplication, no problem. Now imagine the host unloads the first plugin: what will happen to the overridden methods when the second plugin will try to use them as their code (from the first plugin) will not be present in memory anymore? As you can see the only way to fix this design issue is to let a third party element manage the Application instance. This is what I learned from playing with the dll/plugin target. But I couldn't find an pleasant issue until Lorenzo told me his point of view. Lorenzo have explained to me what really bothers him about the nglApplication design. From what I understood the first thing he doesn't like is the fact that he has to create a descendant of nglApplication or nglApplicationBase just to have an entry point in his program. There are two reasons for him to dislike this design. The first one is ideological. He doesn't believe that a program's entry point should be "hidden" inside a class. The exemple he takes is that every C/C++ program have their entry point in a C style function instead of a class (even under windows and mac OS). The second argument is that it forces the user to handle what he considers to be the ngl's kernel (he talks about "ring 0" just as if ngl was an OS). I think the first point is much more about habits than about real design issues (almost all -if not all- real OO languages have their entry point inside a class, look at java for exemple...). However I felt much more concerns about his second argument. He feels that the nglApplication should be renamed something along the line of nglKernel or nglRing0. Let look at the services handled by the ngl application a bit: * Application related: - Application life cycle (init, exit). These are mostly user callbacks. - Command line management. - Application path name. * Debug services: - Log object access. - Console object access. * General OS access: - Clipboard acces * OS Events management: - Event Loop handling. - Idling. Again, the important method is a callback. * OS dependent management: - Low level event loop. - windowing related structures to map OS window handles to nglWindows addresses in X11 & classic mac. - Some timer management for some platforms. - etc... (Lorenzo calls that 'your wires' :-D). As everyone can see these service are really related to the real needs of the application which means we have to provide these services one way or another because their use is quite ubiquitous. What Lorenzo suggest is that most of the low level management should be in an other object that is unique to a process stored and managed by ngl. (hence libngl.dll). He feels that a user should have to inherit, for example the low level event code. He thinks the average programmer doesn't even want to hear from its existance. This object should be hidden and taken care of by ngl for the low level part, and the higl level part should be offered to the developper in an interface that is not far from the current one except the he would just have to use it from outside and never inherit it. The big advantage of this proposition is that it would permit us to have an application object which is completely independant from its environment, whether it be a regular exe of a dll and thus it would help me solve the problem I started with as no particular user piece of code would need to handle the life cycle of the nglApplication object. It would become ngl's duty. Here is the draft of the change: - We remove all user overridable method from nglApplicationBase: virtual void OnInit(); virtual void OnExit (int Code); virtual void OnIdle (nglTime Lap); virtual void PrintUsage(); The OnInit method have to be transformed into a regular C function provided by the programmer like: int nglMain() { // Do something usefull like checking what we received from the command line or something. } This function will be called once in the life time of the program and have the exact same semantic than nglApplicationBase::OnInit(), only it would please Lorenzo ;-) (just kidding!). The three other callbacks being usualy optional I propose we have three globals in the users code (or in a global structure containing these three elements) except they would be transformed into function pointers: if NULL ngl will not call them so the user can affect them some of his functions' pointers. Default: void (*nglExit) (int Code) = NULL; void (*nglPrintUsage)() = NULL; void (*nglIdle) (nglTime Lap) = NULL; I know this is a bit too much C-ish to my tastes, and it even really looks like glut code. Maybe we could also stick with a user class that would provide these three elements and make a C-Like wrapper for it? (implementation detail anyway). OK, we still have to initialize the kernel/nglApplication class and handle the main loop processing if needed. I believe we can easily do that by altering the NGL_CREATE_APP/DLL/PLUGIN macros. For exemple an exe (APP) have to run the event loop so the init macro would look like that: 1- Call the nglInit function to init the ngl subsystem (this function is in libngl.dll). 2- Call nglMain (defined by the user). 3- Run the event loop by calling another NGL function. For the plugins/dll now: 1- Call the nglInit function to init the ngl subsystem (this function is in libngl.dll). 2- Call nglMain (defined by the user). 3- Return to the calling host. I think this scheme is valid for all supported platform (at least it solves all win32 problems I can think off right now). What does nglInit really do? The purpose of nglInit is to make sure a low level subsytem is created and valid (--> App is a valid pointer to a valid nglApplication instance). On th e first call it inits the ngl system (99% of the current init code I think: App = new nglApplication(); App->Init(); etc...), on all next calls it will just increment some reference counter. Every time a code fragment (exe, dll..) is unloaded from memory it will automatically call another function (nglRelease?) which will decrement the reference counter and destroy the subsystem if needed. Another important remaining question: Who calls the dll/plugin startup code? I think the best way to make things smooth for everyone is to make this call rather explicitely inside the plugin's API startup code. For exemple in VST each plugin export one method named main (how original) with some funky arguments. We have then two possibilities: Let some ngl macro handle the VST plugin init and init the ngl app for us all at once, or do the init by ourself by handling the main function by hand and putting the init code there. This is rather a target dependant issue as we will not be able to support all plugin SDK in the world, so I feel both possibilities should be offered to the programmer. I understand that some of you may be reticent to change such a big point of the ngl design (startup code is really important in multiplatform issues) but I really feel these change can help us make the best out of the existing code while changing at most 1% of it for each platform. I also understand the C-like startup interface may look less attracting than the full C++ one (except for Lorenzo maybe ;-P). I hope I didn't bother you too much with this and I'd be very interested in any remark. Considering it is right now (5:54 in the morning) some typos and even stupid ideas may have had their ways to this email so feel free to correct me ;-). I'm planning to implement these changes as soon as possible if we can agree on the resultions we adopt. Thanks in advance, Sebastien (MeeLoo) Metrot Received: from meeloo.net ([62.4.18.112]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17iSvJ-00062j-00 for <[EMAIL PROTECTED]>; Fri, 23 Aug 2002 21:53:21 -0700 Received: from harry ([10.1.1.4]) by meeloo.net with smtp (Exim 3.35 #1 (Debian)) id 17iSvj-0003Tq-00 for <[EMAIL PROTECTED]>; Sat, 24 Aug 2002 06:53:47 +0200 Message-ID: <[EMAIL PROTECTED]> From: "Sebastien Metrot" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> Subject: Re: [NGL-devel] ngl design concerning nglApplication (loonnng...) MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2600.0000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Fri Aug 23 21:54:02 2002 X-Original-Date: Sat, 24 Aug 2002 06:52:17 +0200 Ho, I almost forgot to Thanks Lorenzo for the nice talk and the cool ideas :). MeeLoo ----- Original Message ----- From: "Sebastien Metrot" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Saturday, August 24, 2002 6:47 AM Subject: [NGL-devel] ngl design concerning nglApplication (loonnng...) > Hi all! > > I have been having a very insightful discution with Lorenzo tonight, on the > subject of the design of ngl. The main subject was the dll support issue (as > usual now ;) and some very related design issues in > nglApplication/nglApplicationBase. I'll try to sumarize the main ideas that > we exchanged tonight in this mail. > > First we can say there is a bit of a convergence concerning the needs of a > libngl.dll target lately. [nice hyperbolea to say I kinda changed my mind > ;-P]. For different reasons altogether, Vincent, Lorenzo and even I do feel > it will help solve some issues about application design (I also feel that > doing the work needed to create the target correctly will probably create a > bunch of quirks here and there). > -Vincent needs it to please his linux friends as he allready exaplained to > us :-P. > -Lorenzo needs it because the application he is working on needs to have a > "kernel" dll that is shared by many apps and that these apps may have to > load other dlls. > -I need it for my job at IVS to be able to create an extensible and > strealined video capture system where ngl aware video "drivers" (dlls...) > will be loaded in ngl aware and ngl unaware hosts. I also need it to > strengthen the ngl/nui vst plugin targets (I have some nifty cases > concerning this last bit like multithreading issues and other calamities > that we don't support at all for the moment). > > After toying a bit with the idea (and while implementing two simple > vstplugin samples and the most part of the video driver system) I encoutered > the main problem of the current ngl design: the creator of the > nglApplicationXXX instance is not fixed. It can be an application (exe) or a > dll (a vst plugin, a video driver, etc...). In the simplest cases this is > not a problem: if we just have an application it just has to create the > object. If there is one vst plugin loading in cubase or logic audio it can > also create the object at load time. But there are more complicated > scenarii, for exemple what should happen when loading multiple ngl aware vst > plugins in the same process? Which one should be responsible for creating > and destroying the nglApplication instance? And what must happen if the > plugins are loaded in an ngl application? How can a plugin detect if a valid > nglApplication object has been created or not? Worse: if a plugin creates > the instance, and then the host loads another plugin, the second one will > use the allready existing instance of nglApplication, no problem. Now > imagine the host unloads the first plugin: what will happen to the > overridden methods when the second plugin will try to use them as their code > (from the first plugin) will not be present in memory anymore? > As you can see the only way to fix this design issue is to let a third party > element manage the Application instance. This is what I learned from playing > with the dll/plugin target. But I couldn't find an pleasant issue until > Lorenzo told me his point of view. > > Lorenzo have explained to me what really bothers him about the > nglApplication design. From what I understood the first thing he doesn't > like is the fact that he has to create a descendant of nglApplication or > nglApplicationBase just to have an entry point in his program. There are two > reasons for him to dislike this design. The first one is ideological. He > doesn't believe that a program's entry point should be "hidden" inside a > class. The exemple he takes is that every C/C++ program have their entry > point in a C style function instead of a class (even under windows and mac > OS). The second argument is that it forces the user to handle what he > considers to be the ngl's kernel (he talks about "ring 0" just as if ngl was > an OS). > > I think the first point is much more about habits than about real design > issues (almost all -if not all- real OO languages have their entry point > inside a class, look at java for exemple...). > However I felt much more concerns about his second argument. He feels that > the nglApplication should be renamed something along the line of nglKernel > or nglRing0. Let look at the services handled by the ngl application a bit: > > * Application related: > - Application life cycle (init, exit). These are mostly user callbacks. > - Command line management. > - Application path name. > > * Debug services: > - Log object access. > - Console object access. > > * General OS access: > - Clipboard acces > > * OS Events management: > - Event Loop handling. > - Idling. Again, the important method is a callback. > > > * OS dependent management: > - Low level event loop. > - windowing related structures to map OS window handles to nglWindows > addresses in X11 & classic mac. > - Some timer management for some platforms. > - etc... (Lorenzo calls that 'your wires' :-D). > > As everyone can see these service are really related to the real needs of > the application which means we have to provide these services one way or > another because their use is quite ubiquitous. What Lorenzo suggest is that > most of the low level management should be in an other object that is unique > to a process stored and managed by ngl. (hence libngl.dll). He feels that a > user should have to inherit, for example the low level event code. He thinks > the average programmer doesn't even want to hear from its existance. This > object should be hidden and taken care of by ngl for the low level part, and > the higl level part should be offered to the developper in an interface that > is not far from the current one except the he would just have to use it from > outside and never inherit it. > > The big advantage of this proposition is that it would permit us to have an > application object which is completely independant from its environment, > whether it be a regular exe of a dll and thus it would help me solve the > problem I started with as no particular user piece of code would need to > handle the life cycle of the nglApplication object. It would become ngl's > duty. > > Here is the draft of the change: > - We remove all user overridable method from nglApplicationBase: > virtual void OnInit(); > virtual void OnExit (int Code); > virtual void OnIdle (nglTime Lap); > virtual void PrintUsage(); > > The OnInit method have to be transformed into a regular C function provided > by the programmer like: > int nglMain() > { > // Do something usefull like checking what we received from the command > line or something. > } > > This function will be called once in the life time of the program and have > the exact same semantic than nglApplicationBase::OnInit(), only it would > please Lorenzo ;-) (just kidding!). > > The three other callbacks being usualy optional I propose we have three > globals in the users code (or in a global structure containing these three > elements) except they would be transformed into function pointers: if NULL > ngl will not call them so the user can affect them some of his functions' > pointers. > Default: > void (*nglExit) (int Code) = NULL; > void (*nglPrintUsage)() = NULL; > void (*nglIdle) (nglTime Lap) = NULL; > > I know this is a bit too much C-ish to my tastes, and it even really looks > like glut code. Maybe we could also stick with a user class that would > provide these three elements and make a C-Like wrapper for it? > (implementation detail anyway). > > OK, we still have to initialize the kernel/nglApplication class and handle > the main loop processing if needed. I believe we can easily do that by > altering the NGL_CREATE_APP/DLL/PLUGIN macros. For exemple an exe (APP) have > to run the event loop so the init macro would look like that: > 1- Call the nglInit function to init the ngl subsystem (this function is in > libngl.dll). > 2- Call nglMain (defined by the user). > 3- Run the event loop by calling another NGL function. > > For the plugins/dll now: > 1- Call the nglInit function to init the ngl subsystem (this function is in > libngl.dll). > 2- Call nglMain (defined by the user). > 3- Return to the calling host. > > I think this scheme is valid for all supported platform (at least it solves > all win32 problems I can think off right now). > > What does nglInit really do? > The purpose of nglInit is to make sure a low level subsytem is created and > valid (--> App is a valid pointer to a valid nglApplication instance). On th > e first call it inits the ngl system (99% of the current init code I think: > App = new nglApplication(); App->Init(); etc...), on all next calls it will > just increment some reference counter. Every time a code fragment (exe, > dll..) is unloaded from memory it will automatically call another function > (nglRelease?) which will decrement the reference counter and destroy the > subsystem if needed. > > Another important remaining question: > Who calls the dll/plugin startup code? > I think the best way to make things smooth for everyone is to make this call > rather explicitely inside the plugin's API startup code. > For exemple in VST each plugin export one method named main (how original) > with some funky arguments. > We have then two possibilities: > Let some ngl macro handle the VST plugin init and init the ngl app for us > all at once, or do the init by ourself by handling the main function by hand > and putting the init code there. This is rather a target dependant issue as > we will not be able to support all plugin SDK in the world, so I feel both > possibilities should be offered to the programmer. > > > I understand that some of you may be reticent to change such a big point of > the ngl design (startup code is really important in multiplatform issues) > but I really feel these change can help us make the best out of the existing > code while changing at most 1% of it for each platform. I also understand > the C-like startup interface may look less attracting than the full C++ one > (except for Lorenzo maybe ;-P). I hope I didn't bother you too much with > this and I'd be very interested in any remark. Considering it is right now > (5:54 in the morning) some typos and even stupid ideas may have had their > ways to this email so feel free to correct me ;-). > > I'm planning to implement these changes as soon as possible if we can agree > on the resultions we adopt. > > Thanks in advance, > > Sebastien (MeeLoo) Metrot > > > > > > ------------------------------------------------------- > This sf.net email is sponsored by: OSDN - Tired of that same old > cell phone? Get a new here for FREE! > https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390 > _______________________________________________ > NGL-devel mailing list > [EMAIL PROTECTED] > https://lists.sourceforge.net/lists/listinfo/ngl-devel > Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17ibSj-0002Tr-00 for <[EMAIL PROTECTED]>; Sat, 24 Aug 2002 07:00:26 -0700 Received: (qmail 7187 invoked by uid 508); 24 Aug 2002 14:00:12 -0000 Received: from unknown (HELO wraith) (212.194.151.85) by logic.phpwebhosting.com with SMTP; 24 Aug 2002 14:00:12 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] ngl design concerning nglApplication (loonnng...) Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) In-Reply-To: <[EMAIL PROTECTED]> X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sat Aug 24 07:01:02 2002 X-Original-Date: Sat, 24 Aug 2002 15:57:28 +0200 > Hi all! Hi meeloo :), Hi all! > I have been having a very insightful discution with Lorenzo > tonight, on the subject of the design of ngl. The main subject > was the dll support issue (as usual now ;) and some very related > design issues in nglApplication/nglApplicationBase. > I'll try to sumarize the main ideas that we exchanged tonight > in this mail. > > First we can say there is a bit of a convergence concerning the needs of a > libngl.dll target lately. Yeah, in the end, this is a 'must' anyway for a project of this kind... > > After toying a bit with the idea (and while implementing two simple > vstplugin samples and the most part of the video driver system) I > encoutered the main problem of the current ngl design: the creator > of the nglApplicationXXX instance is not fixed. It can be an application > (exe) or a dll (a vst plugin, a video driver, etc...). In the simplest > cases this is not a problem: if we just have an application it just has > to create the object. If there is one vst plugin loading in cubase or > logic audio it can also create the object at load time. But there are more > complicated scenarii, for exemple what should happen when loading multiple > ngl aware vst plugins in the same process? Which one should be responsible > for creating and destroying the nglApplication instance? And what must > happen if the plugins are loaded in an ngl application? How can a plugin > detect if a valid nglApplication object has been created or not? Worse: if > a plugin creates the instance, and then the host loads another plugin, the > second one will use the allready existing instance of nglApplication, no > problem. Now imagine the host unloads the first plugin: what will happen > to the overridden methods when the second plugin will try to use them as > their code (from the first plugin) will not be present in memory anymore? > As you can see the only way to fix this design issue is to let a third > party element manage the Application instance. This is what I learned > from playing with the dll/plugin target. But I couldn't find an pleasant > issue until Lorenzo told me his point of view. > > Lorenzo have explained to me what really bothers him about the > nglApplication design. From what I understood the first thing he doesn't > like is the fact that he has to create a descendant of nglApplication or > nglApplicationBase just to have an entry point in his program. Well no, to be more precise, I have no problem whith a class entry point or whatever other form could the entrypont take, I just said that we all know that the only way to start a program is : program -> run ! :D (aka : main(argc,argv)) I don't mind if ngl takes this command for itself to start base ngl services etc. and passes to the user's class/function afterwards... What I really care about is sensible modularity and code ownership/segmentation. Besides I'm completely OK with the first row of services described below under 'Application related' label, I would be a fool not to consider sutch needs ... > The second argument is that it forces the user to handle what he > considers to be the ngl's kernel (he talks about "ring 0" just as > if ngl was an OS). Indeed ngl becomes 'almost' an OS when trying to unify the UserApp/Plateform relation, and must be considered that way. ngl IS an 'OS abstraction layer' from the user's point of view and this is what makes it's value, witch is MUTCH more than simply providing an OO Glut-like api. <--! Watch out ! Big Big-UP !--> What really extends the scope of ngl regarding to some Glut-like effort is the unique association of a ritch set of features : Almost complete Input abstraction (if not unified and extensible), Files unification (whith endianneness support), Unified Resource Location (with MIME types support), Windowing abstraction (and mutch more with NUI themable! widgetry), Strings encoding conversion service, Typographic unification (with Opengl rendering!), and soon : Network facilities. In other words ngl has what you need to 'code once -> compile everywhere' but not only OpenGL test applications to show-off at nerds portals, ngl CAN(actually it DOES, see ngl in full effect at Afflelou opticals' shops :D) stand production level developpement. <--! Applause !--> Omar (the singer, not the mollah) saiz : Don't sell yourself short... ;p > However I felt much more concerns about his second argument. He feels that > the nglApplication should be renamed something along the line of nglKernel > or nglRing0. Let look at the services handled by the ngl > application a bit: > * Application related: > - Application life cycle (init, exit). These are mostly user callbacks. > - Command line management. > - Application path name. The above is ok (and needed for nglApp overloaded entry point).. but > * Debug services: > - Log object access. > - Console object access. > > * General OS access: > - Clipboard acces > > * OS Events management: > - Event Loop handling. > - Idling. Again, the important method is a callback. > > * OS dependent management: > - Low level event loop. > - windowing related structures to map OS window handles to nglWindows > addresses in X11 & classic mac. > - Some timer management for some platforms. > - etc... (Lorenzo calls that 'your wires' :-D). > This belongs to 'Ring_0' and would not need to be accessible/visible (I mean the underlying 'wires'/interdependencies), It might be a 'holy wish' though but every effort to make this transparent is worth the try. > As everyone can see these service are really related to the real needs of > the application which means we have to provide these services one way or > another because their use is quite ubiquitous. I would temper this by pointing a confusing semantic short-cut : if it's true that most 'applications' will surely need and make extesive use of these features it's not mandatory that they all reside in the overloadable application entry point (the App object), we can/should identify some rather conceptually independent sub-systems (as there would be two distinct objects for UserApp Console I/O & Logging and NGL internal Debug/Error reporting) and make them laizyly-loadable (read : on-demand). > What Lorenzo suggest is that most of the low level management should be > in an other object that is unique to a process stored and managed by ngl. > (hence libngl.dll). I believe this could solve the process code ownership headache meeloo tryed to depict above : since we don't want interapplication shared data (or leave this as an exercise for the reader ;p) each instance of libngl.dll may have his own Ring_0 section as the root object witch might be the facility needed to manage sub-systems life cycle (As in : NGL::INeedTheEventLoop(UserApp); NGL::WeUseWindowing(UserApp); NGL::LoadThatFontForMe(FontFile); NGL::WhereIsMyConsole(UserApp); or NGL::ItsOkNowYouCanBrushYourTeethAndGoToSleep();) > He thinks the average programmer doesn't even want to hear from its existance. Well, you might not avoid getting in relation with it, but it should clear the App object (and other constructs as nglString,nglFiles,nglFonts..) from unwanted dependencies. > This object should be hidden and taken care of by ngl for the low level part, > and the higl level part should be offered to the developper in an interface that > is not far from the current one except the he would just have to use it from > outside and never inherit it. > > The big advantage of this proposition is that it would permit us > to have an application object which is completely independant from its environment, Witch indeed is the main purpose of ngl... > whether it be a regular exe of a dll and thus it would help me solve the > problem I started with as no particular user piece of code would need to > handle the life cycle of the nglApplication object. It would become ngl's > duty. > > Here is the draft of the change: > - We remove all user overridable method from nglApplicationBase: > virtual void OnInit(); > virtual void OnExit (int Code); > virtual void OnIdle (nglTime Lap); > virtual void PrintUsage(); Why? > The OnInit method have to be transformed into a regular C > function provided by the programmer like: > int nglMain() > { > // Do something usefull like checking what we received from the command > line or something. > } I guess this is not 'necessary'... (my position was not about the entry point look & feel) > This function will be called once in the life time of the program and have > the exact same semantic than nglApplicationBase::OnInit(), only it would > please Lorenzo ;-) (just kidding!). No,no... Keep it an object ;) (errr...,I.., well in fact I'm ok with both solutions, nevermind ...) > The three other callbacks being usualy optional I propose we have three > globals in the users code (or in a global structure containing these three > elements) except they would be transformed into function pointers: if NULL > ngl will not call them so the user can affect them some of his functions' > pointers. > Default: > void (*nglExit) (int Code) = NULL; > void (*nglPrintUsage)() = NULL; > void (*nglIdle) (nglTime Lap) = NULL; > > I know this is a bit too much C-ish to my tastes, and it even really looks > like glut code. Maybe we could also stick with a user class that would > provide these three elements and make a C-Like wrapper for it? > (implementation detail anyway). Yeah really... :D > OK, we still have to initialize the kernel/nglApplication class and handle > the main loop processing if needed. I believe we can easily do that by > altering the NGL_CREATE_APP/DLL/PLUGIN macros. For exemple an exe > (APP) have > to run the event loop so the init macro would look like that: > 1- Call the nglInit function to init the ngl subsystem (this > function is in > libngl.dll). > 2- Call nglMain (defined by the user). > 3- Run the event loop by calling another NGL function. > > For the plugins/dll now: > 1- Call the nglInit function to init the ngl subsystem (this > function is in > libngl.dll). > 2- Call nglMain (defined by the user). > 3- Return to the calling host. > > I think this scheme is valid for all supported platform (at least > it solves > all win32 problems I can think off right now). > > What does nglInit really do? > The purpose of nglInit is to make sure a low level subsytem is created and > valid (--> App is a valid pointer to a valid nglApplication > instance). On th > e first call it inits the ngl system (99% of the current init > code I think: > App = new nglApplication(); App->Init(); etc...), on all next > calls it will ... dunno if the below (ref counting) is really worth the hassle (shared memory across processes etc.), it should be ok to have a ring_0 section by instance, if not I might be missing something obvious..? > just increment some reference counter. Every time a code fragment (exe, > dll..) is unloaded from memory it will automatically call another function > (nglRelease?) which will decrement the reference counter and destroy the > subsystem if needed. BTW The only point I see in needing shared memory across processes is to save memory on the font cache operations, witch I guess is rather expensive (I havent looked at the rendering code in depth though so i might be wrong). > Another important remaining question: > Who calls the dll/plugin startup code? > > I think the best way to make things smooth for everyone is to > make this call rather explicitely inside the plugin's API > startup code. For exemple in VST each plugin export one method > named main (how original) with some funky arguments. We have > then two possibilities: > Let some ngl macro handle the VST plugin init and init the ngl > app for us all at once, or do the init by ourself by handling > the main function by hand and putting the init code there. > This is rather a target dependant issue as we will not be able > to support all plugin SDK in the world, so I feel both > possibilities should be offered to the programmer. > > I understand that some of you may be reticent to change such a > big point of the ngl design (startup code is really important > in multiplatform issues) but I really feel these change can help > us make the best out of the existing code while changing at most > 1% of it for each platform. I also understand the C-like startup > interface may look less attracting than the full C++ one > (except for Lorenzo maybe ;-P). Again... don't change that for me... :/ > I hope I didn't bother you too much with this and I'd be very > interested in any remark. Done. Thank you! for taking the time of writing down that discussion and to care taking it to this point. Of course : I hope I didn't bother you too much with this and I'd be very interested in any remark. ;p Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17iyRS-0003ma-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 07:32:38 -0700 Received: (qmail 2980 invoked by uid 508); 25 Aug 2002 14:32:30 -0000 Received: from unknown (HELO wraith) (212.194.89.89) by logic.phpwebhosting.com with SMTP; 25 Aug 2002 14:32:30 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] ngl design concerning nglApplication (loonnng...) Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) In-reply-to: <[EMAIL PROTECTED]> X-MIMEOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 07:33:03 2002 X-Original-Date: Sun, 25 Aug 2002 16:29:46 +0200 Sometime you spend a lot of words & time trying to explain some simple concepts. Here's a quote from a guy called Adam Moravansky on the GDA list witch summarizes what I was worried about and popped up as a design problem in the dll issue : "Another vital idea is making your code base stratified. Here you have low level services in a base layer, then subclass the lower level classes to provide a subsequent layer of more complex/specialized functionality. To do this right you would make sure that lower levels never depend on the higher levels. And you make it very clear (w. project structure!) which layer a class belongs to." Cheers... Lo. Received: from zerodeux.net ([62.212.104.175]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17j4Rl-0004Vn-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 13:57:22 -0700 Received: from localhost.localdomain (zerodeux.home [192.168.1.3]) by zerodeux.net (Postfix) with ESMTP id 931CDAFCC for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 22:57:19 +0200 (CEST) Subject: Re: [NGL-devel] ngl design concerning nglApplication (loonnng...) From: Vincent Caron <[EMAIL PROTECTED]> To: NGL devel ML <[EMAIL PROTECTED]> In-Reply-To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.7 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 13:58:02 2002 X-Original-Date: 25 Aug 2002 22:57:10 +0200 OK, before going into my own explanations of the lacking notions in NGL, some quick points : * There's no point in doing C in a C++ environment. This is usually Meeloo's job to point this out, but this time both Lorenzo and now myself are stating than the proposed C-ification are not necessary : - the nglMain() is actually making things worse : the whole point of the design discussion is dealing with application or plugin context, this change would simply let the user with all options to wonder where is the proper context, and code things wrong. A lot more on this below. - nothing to add than 'no' on the C callback pointers, I don't even know why it was there * While I see your metaphor, NGL is not an OS nor is a OS wrapper. NGL wraps a lot of things, but 95% of them belong to the C Runtime library or 3rd party libs. The user still needs/is allowed to use the C library, as long as he sticks to the POSIX part (only C89 due to Win32 constraints). There's no such thing as 'low level' API from the NGL user point of view, even today. Still a lot more on this confusing matter below. -- A few weeks ago we tried to improve the semantics of nglApplication and tie its life cycle to its hosting process, making some plugins feasible. IMHO the last mail is rather confusing, talks a lot about implementation details without clearing out important notions. So I'll try to do it there. The expected conclusion is that our minds need a good update before the code gets changed. Everything is about the program's running context. In other words the 'process', a hopefully notion you'll find in any OS nowadays. Inter-process communication is another topic (Lorenzo mentioned such a thing), here we only deal with the kernel task context running our code, ie. our process. We'll also see that threading is not an issue that affects our design problem. The OS role is to virtualize hardware ressources, and pretend to every process that they own it. An OS never gives you a mean to access directly an hardware ressource (other than hazardous and creepy APIs :)), but rather lends you a 'proxy' ressource, which only opens a controlled and windowed access to that ressource. The most simple example is the default file handles (stdout, stderr, stdin). Any POSIX kernel will create those file objects for every process. From the kernel point of view, you have one hardware console (out 0xb800,xx :)), but many proxies : when a process issues something on the console file handles, the kernel will update the hardware console accordingly. In user space we can in turn virtualize some ressources. The console example is still valid : wether you're running Windows (cmd), X-Window (xterm) or plain console (getty), you know that in any case you can read and write in a per-process console, whatever graphical form it takes. -- Back to NGL : we're trying to virtualize the running context in both plain application and plugin cases. Before guessing how to virtualize this, let's see what we have to deal with (as NGL implementors) : - wether we are in an application or a plugin context, we have the same process context : same memory, same view on the kernel objects (opened files, etc) - in a NGL application, we provide our context : this a basic abstraction of the C library, and stands as a layer between the OS and NGL user (GetPath(), GetName(), etc) - in a NGL plugin (VST, etc), we have one more context whose role is to give a controlled view to the host application. We implicitly inherent the process context (try calling exit() if you don't trust me :)), and own the same view to the OS as the host does. The 3rd point is actually our main design issue. Two problems arise : - Some nglApplication methods do not make sense in a plugin context, or worse, have another meaning. Take OnInit() : an application context init, this does not need a lot of documentation. This is actually like writing a plugin for a special host : the kernel ! Everyone knows how a process life works and how it interacts with the kernel, at least using the libc (main(), exit()). We don't document it. This is a lot different for host applications : why you'll find some similarities, they actually all define their very own concepts, where OnInit() has no trivial equivalent. Trying to map nglApplicationBase::OnInit() to different entry points (OS or application host) is a Bad Mistake (TM). This could be something like nglVSTPlugin::OnStuff(), where this method would perfectly map with an existing 'stuff' entry point in the VST plugin API. - nglApplication might expose more services than a given host would do to its client plugin. An host may want to provide either a restrained nglApplication context to its plugin, either a higher-level interface. The last point raises in turn NGL old design debates. NGL implementation needs to reach a 'running context' from any point of the code, this is our famous 'App' global. This 'running context' main role is to : - Hold the main loop : under Unix, all event generators object (nglWindow, nglConsole, nglTimer, etc) register to the main loop via a nglApplicationBase private call. Under Windows, since the message loop is mainly held by the kernel, the nglApplication can be mostly bypassed. - Hold the unique 'application console' : the reasonnable assumption is one console per process. The fact that there can be only one nglConsole instance per process context makes it functionnaly equivalent to printf(stdout). However the console object is not stored in kernel side, and we had some linker headaches... - Hold the unique 'application log' : idem ! -- Let's try to draw some conclusions now. - We need to identify an object/class mapping to the 'OS process context'. This need not be an instance, it can be a 'pure static' class. Actually, if it is a OS process context wrapper, it should only deal with kernel objects and not need its own members (we know that it's more complicated than that, the libc has a 'errno' global for instance). Looking at nglApplicationBase doc, there's actually almost nothing that should be kept, it's merely application specific : there's no such thing as GetPath(), GetName() or GetArg() in a plugin. - Since the 'application console & log' are very handy concepts and that NGL use them a lot, we should keep them. But they would be more exactly 'process console & log' : their instance would either belong to the 'process context class' exposed above, or rely on their own globals. nglLog has been specially designed to multiplex a lot of information (domain & verbosity) to a single media (one console, one file, etc). I don't see the point in having a console popping for any NGL plugin. And it would be embarassing to implement on native Unix (including MacOSX) consoles. * A simple console creation policy can be set up : a console should be instantiated only once. It can be a NGL host (plugins will have no choice but using the host's console, seems more than reasonable), or it can be the first loaded NGL plugin in a non-NGL host. * Or we can allow the creation of any console objects and let the user bind it as the 'current application console'. In other words, console creators own the console (and must destroy it when finished), and set the global console pointer to their own. Kind of messy IMHO. - There should be one context per running target : * one nglApplication instance for... applications * one nglTotoPlugin instance for each Toto's plugin And they should be ready to exist in the same process. Each one is the specific 'running context'. Conceptually, nglApplication looks like another plugin (the 'OS plugin' I was talking about actually). Technically, we should expect this context to hold the main loop code. Which is a good thing, since we expect it to be pretty different for every plugins and the application itself. Now we have another problem : 'event' classes (nglWindow, nglTimer) need to know which running context to use, to register to the event loop. There's no way around this : the running context must be a paremeter of these class constructors. -- Conclusion of the conclusion : applications and plugins are not the same beast. Not the same setup interface, not the same code (under Unix this is event a drastic change in event handling). There's no gain in trying to tweak nglApplication to make the things work. All would be simple if NGL was only a regular 3rd party library, but it's a framework and does a lot of implicit things. If you want to use NGL/NUI for plugins and applications in any combination, you'll have to mentally split NGL : the library part, the framework part. Now this is easy, we just have to dig those implicit choices that we took when whe werer only thinking about an application framework : - the famous App application global : should not exist. Any class which needs access to 'running context' services (registering events, system handles, etc) should be provided with the given context. This currently would mean : nglWindow::nglWindow(nglContextBase* pCtx, nglWindowInfo& rInfo) Where nglContextBase would be the base class of actual nglApplication or nglVSTPlugin instances, providing the required event/handle registry. This is expected for nglConsole, nglWindow, nglTimer, future network classes, and maybe nglVideoMode and nglVisual. - since we don't want to lose NGL logging services and also don't want to provide a nglLog object to every NGL class, we can still provide those two services as globals (like stdout), being equally used by the application and any plugins in the same process. We just need a policy about the objects life cycle (heck, in a process _anybody_ can close() stdout and reopen it with dup2() without anybody noticing, and it's actually very handy for transparent redirections !) -- Last note. Two ways to implement this plugin framework : - the hackery around nglApplication - the real thing, exposing the running context to the user, and without globals The first item is plainly horrible. Before even releasing NGL we would already provide cluttered classes. And I don't personnaly see how to either code or distribute the plugin specific code whith such a mess. The second item might be interesting, but is : - out of schedule - something again painful and complex, while some basic classes are not yet finalized nor here (image, network) - forcing us to complexify the API, in other words removing the App global and loosing a bunch of comfortable assumptions. I can perfectly live without them, but I really don't want to expect the same from NGL users. Maybe 0,01% of them will do VST plugins. Maybe twice a Maya plugin. My position is as follow : as long as plugin development brings in good ideas (removing plugin specific code from nglApplication, modularizing entry and event handling code, etc), I'll try to apply them. If it's in the way of the 'second item' above, I might be interested too. And more generally, any effort to cleanly separate the application specific code from the plugin specific code will be welcomed. Anything else should stay in your local working repository unless you like to be flamed :) Received: from zerodeux.net ([62.212.104.175]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17j4at-0006az-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 14:06:48 -0700 Received: from localhost.localdomain (zerodeux.home [192.168.1.3]) by zerodeux.net (Postfix) with ESMTP id B1402AFCC for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 23:06:47 +0200 (CEST) Subject: Re: [NGL-devel] ngl design concerning nglApplication (suggestion) From: Vincent Caron <[EMAIL PROTECTED]> To: NGL devel ML <[EMAIL PROTECTED]> In-Reply-To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.7 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 14:07:03 2002 X-Original-Date: 25 Aug 2002 23:06:38 +0200 On Sun, 2002-08-25 at 22:57, Vincent Caron wrote: > - the famous App application global : should not exist. > Any class which needs access to 'running context' services > (registering events, system handles, etc) should be provided with the > given context. This currently would mean : > > nglWindow::nglWindow(nglContextBase* pCtx, nglWindowInfo& rInfo) > > Where nglContextBase would be the base class of actual nglApplication > or nglVSTPlugin instances, providing the required event/handle registry. > > This is expected for nglConsole, nglWindow, nglTimer, future network > classes, and maybe nglVideoMode and nglVisual. I just realized there's a sort of third way : continue to provide context-less constructors to these classes, and let them still use the 'App' global. Then the only constraint would be : "plugin developers, there's no such thing as App, pass your running context everywhere". Application developers would work just as we do today. Now what happens if a stupid/lazy user creates a nglWindow from a plugin without giving the running context ? - non-NGL host : we obviously have init'ed App to NULL from the plugin entry point, so we detect the condition and rant - NGL host : works, automatically uses the host context, is it OK ? Received: from meeloo.net ([62.4.18.112]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17j8GY-0000eB-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 18:02:03 -0700 Received: from harry ([10.1.1.4]) by meeloo.net with smtp (Exim 3.35 #1 (Debian)) id 17j8H1-0007qM-00 for <[EMAIL PROTECTED]>; Mon, 26 Aug 2002 03:02:31 +0200 Message-ID: <[EMAIL PROTECTED]> From: "Sebastien Metrot" <[EMAIL PROTECTED]> To: "NGL devel ML" <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> Subject: Re: [NGL-devel] ngl design concerning nglApplication (loonnng...) MIME-Version: 1.0 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2600.0000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 18:03:01 2002 X-Original-Date: Mon, 26 Aug 2002 03:00:44 +0200 ----- Original Message ----- From: "Vincent Caron" <[EMAIL PROTECTED]> To: "NGL devel ML" <[EMAIL PROTECTED]> Sent: Sunday, August 25, 2002 10:57 PM Subject: Re: [NGL-devel] ngl design concerning nglApplication (loonnng...) > * There's no point in doing C in a C++ environment. This is usually > Meeloo's job to point this out, but this time both Lorenzo and now > myself are stating than the proposed C-ification are not necessary : > Ok, the interface doesn't NEED to be that way but for DLLs to work correctly I'll have to make the entry point a C function. There's just no other way around. I.E: I can hide it but it'll be there. (exporting C++ classes from a dll and loading them by hand at runtime is quite tedious under win32). > - the nglMain() is actually making things worse : the whole point of > the design discussion is dealing with application or plugin context, > this change would simply let the user with all options to wonder where > is the proper context, and code things wrong. A lot more on this below. > nglMain is a LOW level interface. We can perfectly create a bunch of entry point classes that do the actual work for their respective targets (exe, vst, maya, netscape, max, etc...). > - nothing to add than 'no' on the C callback pointers, I don't even > know why it was there > I don't have much choice. > * While I see your metaphor, NGL is not an OS nor is a OS wrapper. NGL > wraps a lot of things, but 95% of them belong to the C Runtime library > or 3rd party libs. The user still needs/is allowed to use the C library, > as long as he sticks to the POSIX part (only C89 due to Win32 > constraints). There's no such thing as 'low level' API from the NGL user > point of view, even today. Still a lot more on this confusing matter > below. > I don't agree with you on this one. I really use NGL as if it actually was my OS. The abstraction offered is just perfect for 99% of my needs, whatever the context may be: standalone applications, VST plugins, maya plugins, mixed context applications (I use NGL core OS abstraction & tools in some plain Win32 application very happily!). > A few weeks ago we tried to improve the semantics of nglApplication and And we failed. This was just the begining of the journey and we just missed the principle: we must totaly separate what is the users' objects and what is really managed by ngl. This is really easy, at least on Win32 and Carbon. I understand that it may be quite painful to plug anything in the X11 event loop under unix but you'll have to find a solution when it's needed: when the first unix ngl plugin targets will be created (in a loooong time from what I see). > > This is a lot different for host applications : why you'll find some > similarities, they actually all define their very own concepts, where > OnInit() has no trivial equivalent. Trying to map > nglApplicationBase::OnInit() to different entry points (OS or > application host) is a Bad Mistake (TM). This could be something like > nglVSTPlugin::OnStuff(), where this method would perfectly map with an > existing 'stuff' entry point in the VST plugin API. > Ok, no pbm. > - nglApplication might expose more services than a given host would do > to its client plugin. An host may want to provide either a restrained > nglApplication context to its plugin, either a higher-level interface. > Still no pbm, i'm working on dedicated targets with their own entry point and helper classes for vst, maya or whatever... > > The last point raises in turn NGL old design debates. NGL implementation > needs to reach a 'running context' from any point of the code, this is > our famous 'App' global. This 'running context' main role is to : > > - Hold the main loop : under Unix, all event generators object > (nglWindow, nglConsole, nglTimer, etc) register to the main loop via a > nglApplicationBase private call. Under Windows, since the message loop > is mainly held by the kernel, the nglApplication can be mostly bypassed. > THIS is the main issue. It is easily solved under every OS except Unix/X11. > - Hold the unique 'application console' : the reasonnable assumption is > one console per process. The fact that there can be only one nglConsole > instance per process context makes it functionnaly equivalent to > printf(stdout). However the console object is not stored in kernel side, > and we had some linker headaches... > This is mainly a non-issue. There are many reasons to want multiple consoles in NGL as we'll see later on. > Let's try to draw some conclusions now. > > - We need to identify an object/class mapping to the 'OS process > context'. This need not be an instance, it can be a 'pure static' class. > Actually, if it is a OS process context wrapper, it should only deal > with kernel objects and not need its own members (we know that it's more > complicated than that, the libc has a 'errno' global for instance). > Looking at nglApplicationBase doc, there's actually almost nothing that > should be kept, it's merely application specific : there's no such thing > as GetPath(), GetName() or GetArg() in a plugin. > I don't understand at all what this pure virtual class would hold: what would be its interface? > - Since the 'application console & log' are very handy concepts and > that NGL use them a lot, we should keep them. But they would be more > exactly 'process console & log' : their instance would either belong to > the 'process context class' exposed above, or rely on their own globals. > nglLog has been specially designed to multiplex a lot of information > (domain & verbosity) to a single media (one console, one file, etc). I > don't see the point in having a console popping for any NGL plugin. And > it would be embarassing to implement on native Unix (including MacOSX) > consoles. > Then you're quite short sighted my friend, and I propose you use NGL a bit more than you "make" it :-). I very often am in the situation where I have at least 2 or 3 diferent plugin instances loaded in an application. If there is only one console, how can I send commands to any plugin? Unless there is a way to register an input handler in the console for every plugin I don't see how such a console could be of any other use than dumping infos. > * Or we can allow the creation of any console objects and let the user > bind it as the 'current application console'. In other words, console > creators own the console (and must destroy it when finished), and set > the global console pointer to their own. Kind of messy IMHO. > I find this to be quite reasonable in fact, and it offers maximum flexibility! > > - There should be one context per running target : > > * one nglApplication instance for... applications > * one nglTotoPlugin instance for each Toto's plugin > Then nglApplication should be totaly exploded and just contain what is needed to handle the user's code, every thing else would make the thing totaly horrible. For exemple there could be 120 diferent plugin bindings available for ngl: do we really want 120 nglWindow constructor to init them? I guess not (at least I don't). As I said earlier I have some very simple and straiforward solutions for all these problems under win32 & Carbon (not classic) where two main targets would permit to keep 99.5 percent of the current code without actually being a hack of any kind. It just needs a good way to separate OS/Target dependant code from the actual user code which is not the way you are showing us from what I understand and the proposed OS context would tie even a little bit more the users code to its particular environement instead of making it a totaly diferent object. > > Now we have another problem : 'event' classes (nglWindow, nglTimer) need > to know which running context to use, to register to the event loop. > There's no way around this : the running context must be a paremeter of > these class constructors. > Again, this is a very unix specific problem, and even then the event loop is a singleton. Even if the external solutions to the event loop problem may be diferent depending on the host but there should be only one interface to do that. As the event loop is a singleton (by design, even if ngl doesn't own the event loop there should be only one per process) we can really live with ONE global pointer to the NGL kernel. This NGL kernel providing what's needed to tie any ngl resource to the event loop. > Conclusion of the conclusion : applications and plugins are not the same > beast. Not the same setup interface, not the same code (under Unix this > is event a drastic change in event handling). There's no gain in trying > to tweak nglApplication to make the things work. > We don't want to tweak it, we want to tear it appart... > > - the famous App application global : should not exist. > Any class which needs access to 'running context' services > (registering events, system handles, etc) should be provided with the > given context. This currently would mean : > > nglWindow::nglWindow(nglContextBase* pCtx, nglWindowInfo& rInfo) > > Where nglContextBase would be the base class of actual nglApplication > or nglVSTPlugin instances, providing the required event/handle registry. > No, as I explained this is not needed in any way. > > Last note. Two ways to implement this plugin framework : > > - the hackery around nglApplication > - the real thing, exposing the running context to the user, and without > globals > No no no. Here is what I proposed, actually translated to code: In libngl.dll: // We have a pure virtual class that define the basic interface to manage the low level event loop management for the low level objects. // This base class is diferent for every OS. (obviously, we dont even need it under win32 for exemple). class nglKernelBase { public: virtual void AddRef() = 0; virtual void Release() = 0; bool AddWindowEventLoop(nglWindow* pWindow); bool DelWindowEventLoop(nglWindow* pWindow); bool AddTimerEventLoop(nglTimer* pTimer); bool DelTimerEventLoop(nglTimer* pTimer); // etc... }; // We then have one event loop management class for each target: class nglApplicationKernel : private nglKernelBase { public: nglApplicationKernel(int argc, char** argv) { mRef = 1; } virtual ~nglApplicationKernel(); private: // This method actually runs the ngl application event loop void RunEventLoop(); // Only main () can access it as we are in an executable: friend int main(int argc, char** argv); void AddRef() { mRef++; } void Release() { mRef--; if (!mRef) delete this; } bool AddWindowEventLoop(nglWindow* pWindow) { // actually implement the code needed to add a nglWindow to the NGL event loop } bool DelWindowEventLoop(nglWindow* pWindow); bool AddTimerEventLoop(nglTimer* pTimer); bool DelTimerEventLoop(nglTimer* pTimer); private: int mRef; }; class nglMayaKernel : private nglKernelBase { public: nglMayaKernel(... actual maya specific arguments...) { mRef =1; } virtual ~nglMayaKernel(); private: void AddRef() { mRef++; } void Release() { mRef--; if (!mRef) delete this; } bool AddWindowEventLoop(nglWindow* pWindow) { // actually implement the code needed to add a nglWindow to the hosts event loop } bool DelWindowEventLoop(nglWindow* pWindow); bool AddTimerEventLoop(nglTimer* pTimer); bool DelTimerEventLoop(nglTimer* pTimer); int mRef; }; // We then have (still inside libngl.dll) ONE global pointer to the actual event manager object: nglKernelBase* gpKernelBase = NULL; // This object is actually used by ALL ngl objects that need to register themselves with the event loop: they all use the same interface to do so. // Lastly we have the actuel user defined objects that will hold their entry points: class nglUserApplication { public: virtual void OnInit(); virtual void OnExit(); virtual void OnIdle(); }; class nglMayaPlugin { public: virtual MObject* OnInit(MObject* pObject); virtual MObject* OnExit(MObject* pObject); }; //////////////////////////////////////////////// OK Now we have to find a way to logically create this object, and in fact the mecanism is quite straight forward: In an application we call the application startup code which is basically like this: extern nglKernelBase* gpKernelBase; int main (int argc, char* argv) { if (gpKernelBase) { // WTF? This is an application, this object should be null!!! return 1; } else { nglApplicationKernelBase* pBase = new nglApplicationKernel(arc, argv); gpKernelBase = pBase; UserApplication* pApp = new UserDefinedApplication(); pApp->OnInit(); int ret = pBase->RunEventLoop(); pApp->OnExit(); delete gpKernelBase; return ret; } } /////////////////////////////////////////////// In a plugin what we do is this: extern nglKernelBase* gpKernelBase; // Let's suppose this is the official entry point of this particular API (let say maya...): MObject* MayaEntryPoint (MObject* pObject) { if (gpKernelBase) { // Ok, someone allready created the event loop manager, we are ready to roll... // We just have to increment the ref counter: gpKernelBase->AddRef(); } else { gpKernelBase = new nglMayaKernel(pObject); } // Call the user's entry point nglMayaPlugin* pPlugin = new nglMayaUserPlugin(); return pPlugin->OnInit(pObject); } // And the maya exit MObject* MayaExitPoint (MObject* pObject) { gpKernelBase->Release(); } ////////////////////////////// What are the benefits of this: When we are in a maya plugin there is only one thing that we are sure about: we can rely on the maya API to acces the underlying message loop so if there is no message loop created we can at least ask libngl to create one for us. If another plugin gets loaded it will find that glKernelBase is not null, which means that there is allready some ngl code that created a way to acces the message loop. If the application host is some NGL application the first thing it will do is create message loop handler and affect it to glKernelBase so that any ngl plugin is loads will find a suitable message loop handler and thus will just have to use it instead of creating its own. The mecanism is quite simple and straightforward, and I have yet to be shown a particular case where is doens't work correctly. The BIG advantage is that we have a unified way to share the message loop even when the underlying system doesn't permits this explicitely. I repeat this mecanism is NOT needed under Win32 and MacOS where a simple startup code is mostly needed to register some window classes and all the rest totaly decentralized. > The first item is plainly horrible. Before even releasing NGL we would > already provide cluttered classes. And I don't personnaly see how to > either code or distribute the plugin specific code whith such a mess. > > The second item might be interesting, but is : > > - out of schedule > - something again painful and complex, while some basic classes are not > yet finalized nor here (image, network) > - forcing us to complexify the API, in other words removing the App > global and loosing a bunch of comfortable assumptions. I can perfectly > live without them, but I really don't want to expect the same from NGL > users. Maybe 0,01% of them will do VST plugins. Maybe twice a Maya > plugin. > For the moment the simple stats are these ones: There are three NGL users. Among them at least 1 needs the maya API and VSTplugins and the Other needs a decentralized way to use ngl without having to mess with the current way of doing things. You CAN live without this feature while WE can't. The actual change to the code really concerns at most 1% of it: the entry point and the main loops. The unix platform currently support only maya plugins that doesn't use the ngl's windows, so you don't even have to really hack your code to use this kind of infrastructure, and I'm even pretty sure your actual code allready looks a lot like what I just described (nglWindows have to register with nglApplicationBase to get to the main loop, we would just change the object with which they'd have to register...). > My position is as follow : as long as plugin development brings in good > ideas (removing plugin specific code from nglApplication, modularizing > entry and event handling code, etc), I'll try to apply them. If it's in > the way of the 'second item' above, I might be interested too. And more > generally, any effort to cleanly separate the application specific code > from the plugin specific code will be welcomed. Anything else should > stay in your local working repository unless you like to be flamed :) > This proposal can be implemented in a matter of 2 or 3 days on all supported platforms. It isn't a hack. It would solve 99% of the problem I'm facing at the moment in order to create the win32/mac os dll target that can be seemlesly used as a plugin dll (explicit linking), a support dll (implicit linking) and a standalone executable (that can even use plugins and support dlls and share one NGL lib with them). I really hope you'll understand what kind of solution we're after. And we need it FAST (ow, and i really don't want to have to fork the CVS or even implement this in a branch, it would be sooo stupid/sad!). MeeLoo Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17j8wq-000712-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 18:45:45 -0700 Received: (qmail 16971 invoked by uid 508); 26 Aug 2002 01:45:37 -0000 Received: from unknown (HELO wraith) (212.194.89.89) by logic.phpwebhosting.com with SMTP; 26 Aug 2002 01:45:37 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] ngl design concerning nglApplication (loonnng...) Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) In-Reply-To: <[EMAIL PROTECTED]> X-Mimeole: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 18:46:01 2002 X-Original-Date: Mon, 26 Aug 2002 03:42:53 +0200 ---- > On the OS topic I must admit a better term would have been plateform... > * While I see your metaphor, NGL is not an OS nor is a OS wrapper. NGL > wraps a lot of things, but 95% of them belong to the C Runtime library > or 3rd party libs. The user still needs/is allowed to use the C library, > as long as he sticks to the POSIX part (only C89 due to Win32 > constraints). Well I guess CRT & other 3rd party libs have made ngl possible (among many other great things). POSIX has standardized most of CRT behaviour and makes a developper confident in that 'He Knows C Kung Fu' witch tends to let him forget that every compiler has it's caveats (see Templates/STL...) and most of all : the effort that every OS hacker/merchant had to make in abstracting the HW to be complient (witch is great IMHO if not a pleonasm). Other brilliant 3rd party libs (as freetype or libjpg) were summoned into ngl, and efforts were made to give a unique interface for ie. getting what time it is. Witch lead ngl to the point that it gives an unified abstraction of the plateform/environnement on lots of features a 'modern applications' developper needs. In the process of what, desing decisions were needed to be made, and will be exposed for adoption. You call this a framework or whatever, that doesn't change what developper's needs ngl will fullfill ! NGL might not be an ANSI candidate, We'll like it all the same ;p ---- > Back on Design Issues... > There's no such thing as 'low level' API from the NGL user point of view Nope ! But NGL definitely has IT's low levels (even if it doesn't has a single byte of hand coded asm nor interruption handling), ngl isn't a flat bunch of features. What I try to mean by low level (in the discussion with Seb & my last post) is precisely what makes me mad about the App object's actual status : "what the hell is that String class that needs to know what an Application is !!". nglApplication is supposed to be built on TOP of all. Stuff that relies only on CRT (witch is an intermediate level), as in - concepts that does not need wrap os specific stuff - (like stings, pathes, files*.. in opposition to windows ie.) but gives the developper an easyer way to use/think about it, may all need to relate to some universally accessible resources (mainly for debug/error reporting). But actually those resources in ngl are not hardware in opposition to the tty you talk about in the 'Mind Update' thus they don't need to be virtualized, they just need to be universally accessible from any upper level. > We need to identify an object/class mapping to the 'OS process > context'. This need not be an instance, it can be a 'pure static' class. Right! > The OS role is to virtualize hardware ressources, and pretend to every > process that they own it. According to this definition ngl is not an OS ;p since processes would really own it (it is not hardware). </quote> This object should be hidden and taken care of by ngl for the low level part, and the higl level part should be offered to the developper in an interface that is not far from the current one except the he would just have to use it from outside and never inherit it. The big advantage of this proposition is that it would permit us to have an application object which is completely independant from its environment whether it be a regular exe or a dll. </quote> > - the famous App application global : should not exist. Rrright ! but the problem is App, not global ... > Any class which needs access to 'running context' services > (registering events, system handles, etc) should be provided with the > given context. This currently would mean : > > nglWindow::nglWindow(nglContextBase* pCtx, nglWindowInfo& rInfo) Nope ! Any class which needs access to 'running context' services would access it as usual : thru a global object (witch is not the application but a real orthodox singleton). Why make this so over complicated? > - since we don't want to lose NGL logging services and also don't want > to provide a nglLog object to every NGL class, we can still provide > those two services Thru the same global object (witch is not the application). The only tricky thing I can see is the EntryPoint definition. Witch will need to be defined alternatively on every target (main/winMain/dllMain/plugMain) as a nested interface declaration for the appropriate Top level class (Application/Plugin) or not defined at all if no EntryPoint forwaring is needed (intermediate DLL). ... I'll try an explicit suggestion asap, I think I need to post this to keep in sync.. More to come... Lo. Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17j9KY-0004oJ-00 for <[EMAIL PROTECTED]>; Sun, 25 Aug 2002 19:10:14 -0700 Received: (qmail 20318 invoked by uid 508); 26 Aug 2002 02:10:03 -0000 Received: from unknown (HELO wraith) (212.194.89.89) by logic.phpwebhosting.com with SMTP; 26 Aug 2002 02:10:03 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] ngl design concerning nglApplication (loonnng...) Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) In-Reply-To: <[EMAIL PROTECTED]> X-Mimeole: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Sun Aug 25 19:11:01 2002 X-Original-Date: Mon, 26 Aug 2002 04:07:18 +0200 > > We need to identify an object/class mapping to the 'OS process > > context'. This need not be an instance, it can be a 'pure static' class. > > Right! Yuk! An instance it needs to be but a singleton better is (with it's static access).. saiz Yoda Lo. Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17jLWX-0004jN-00 for <[EMAIL PROTECTED]>; Mon, 26 Aug 2002 08:11:25 -0700 Received: (qmail 22627 invoked by uid 508); 26 Aug 2002 15:11:12 -0000 Received: from unknown (HELO wraith) (213.44.249.35) by logic.phpwebhosting.com with SMTP; 26 Aug 2002 15:11:12 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) X-Mimeole: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal In-Reply-To: <[EMAIL PROTECTED]> Subject: [NGL-devel] Network facilities intentions? Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Mon Aug 26 08:12:03 2002 X-Original-Date: Mon, 26 Aug 2002 17:08:28 +0200 Hi Seb,02.. Is there a place where you state about some intention regarding the networking topic in ngl? I'm actually thinking about it for my project and trying to plan a transparent (disk/network/archive) file access system based on URL semantics, witch allready provides for file:// http:// ftp:// and where I could aggregate something like : zip:// or rar:// and so on ... Ideally sutch a system would hide some local caching mechanism. Since ngl has allready some (local) file system access layer I was thinking it could be the plug-in point for sutch a feature... I don't know if this kind of stuff is in the scope of what you planned (what I remember from discussions with Seb about a year ago, preocupations where on a socket scale and about asynchonous operations) but if you like the idea (witch I believe would nicely fit into ngl) i'll be glad to discuss it here. Lo. Received: from zerodeux.net ([62.212.104.175]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17jTDb-0004jO-00 for <[EMAIL PROTECTED]>; Mon, 26 Aug 2002 16:24:23 -0700 Received: from localhost.localdomain (zerodeux.home [192.168.1.3]) by zerodeux.net (Postfix) with ESMTP id B60E9AFC3 for <[EMAIL PROTECTED]>; Tue, 27 Aug 2002 01:24:21 +0200 (CEST) Subject: Re: [NGL-devel] ngl design concerning nglApplication (loonnng...) From: Vincent Caron <[EMAIL PROTECTED]> To: NGL devel ML <[EMAIL PROTECTED]> In-Reply-To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.8 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Mon Aug 26 16:25:04 2002 X-Original-Date: 27 Aug 2002 01:24:14 +0200 OK. Now you can see how much I'm globally tired :) And here's the (brand new) missing data : I'm officially on vacations from 31/08 thru 16/09. Yes, in a place where there are no cell phones nor modems. I'll nazily inspect the new framework implementation details (as usual), but I'll only care about headers. I don't care if the Unix code breaks, I'll fix it later. Meeloo's sample code is not quite right but was enough to clearly explane things. It would be nice if Meeloo could post the plain and simple public interfaces of the (new) nglApplication and nglApplicationKernel (we'll backport the doc later). We'll discuss details from there. Meanwhile I'm not sure if I'll keep nglApplicationBase (but I'll still support the nogfx target), we'll se in the details. nglLog : I guess it'll move in KernelBase and be the "libngl.dll's log" for now. We'll see _later_ for a NO_LOG build option for those so inclined. nglConsole : should move as an abstract ConsoleBase (as expected from a long time), and SystemConsole should be a singleton tied to our current implementation (tty for Unix, home-made one for Windows). User can also create any UserConsole from here, and connect any nglLog to them for instance. We should also see that _later_. -- I have an important pending patch on nglWindow (removing flags), which I sadly could not finish due to unexpected busy nights. I'm trying to finish it now, please expect things to break in CVS for 24 or 48h, sorry. Received: from zerodeux.net ([62.212.104.175]) by usw-sf-list1.sourceforge.net with esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17jTNr-0005V0-00 for <[EMAIL PROTECTED]>; Mon, 26 Aug 2002 16:34:59 -0700 Received: from localhost.localdomain (zerodeux.home [192.168.1.3]) by zerodeux.net (Postfix) with ESMTP id C6781AFC3 for <[EMAIL PROTECTED]>; Tue, 27 Aug 2002 01:34:59 +0200 (CEST) Subject: Re: [NGL-devel] Network facilities intentions? From: Vincent Caron <[EMAIL PROTECTED]> To: NGL devel ML <[EMAIL PROTECTED]> In-Reply-To: <[EMAIL PROTECTED]> References: <[EMAIL PROTECTED]> Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Mailer: Ximian Evolution 1.0.8 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Mon Aug 26 16:36:01 2002 X-Original-Date: 27 Aug 2002 01:34:52 +0200 On Mon, 2002-08-26 at 17:08, Lorenzo Pastrana wrote: > > Hi Seb,02.. > Is there a place where you state about some intention regarding the > networking topic in ngl? It's planned, it's located at a precise place in the TODO file. This will be a simple socket C++ wrapper. then we'll do networked nglStreams. Then we'll eventually consider something like nglURL that would support a 'protocol handler' plugin registry, and give you the according streams. So much work, so little time. If I can find a way to use NGL at work, this would change things a lot. We'll see. Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17jU6V-0008Px-00 for <[EMAIL PROTECTED]>; Mon, 26 Aug 2002 17:21:07 -0700 Received: (qmail 31539 invoked by uid 508); 27 Aug 2002 00:20:59 -0000 Received: from unknown (HELO wraith) (212.194.123.31) by logic.phpwebhosting.com with SMTP; 27 Aug 2002 00:20:59 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] Network facilities intentions? Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) X-Mimeole: Produced By Microsoft MimeOLE V5.50.4807.1700 Importance: Normal In-Reply-To: <[EMAIL PROTECTED]> Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Mon Aug 26 17:36:04 2002 X-Original-Date: Tue, 27 Aug 2002 02:18:12 +0200 > > It's planned, it's located at a precise place in the TODO file. This mmmh... ok, didn't supected this was not the right time to ask ... I actually saw the mention in the TODO.. my question was about further details.. nevermind. ;) > will be a simple socket C++ wrapper. then we'll do networked nglStreams. BTW, I was looking at the w3c web lib (thinking of a possible support) witch I didn't mentionned.. so my question may have appeared a little 'pushy' (like too high order). > Then we'll eventually consider something like nglURL that would support > a 'protocol handler' plugin registry, and give you the according > streams. > > So much work, so little time. Well, we might have a brand new guy in a couple of weeks.. ;) > If I can find a way to use NGL at work, this would change things a lot. > We'll see. > Yep! Lo. Received: from logic.phpwebhosting.com ([66.33.1.213]) by usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17jjYk-0005a8-00 for <[EMAIL PROTECTED]>; Tue, 27 Aug 2002 09:51:18 -0700 Received: (qmail 2057 invoked by uid 508); 27 Aug 2002 16:51:05 -0000 Received: from unknown (HELO wraith) (212.194.130.8) by logic.phpwebhosting.com with SMTP; 27 Aug 2002 16:51:05 -0000 From: "Lorenzo Pastrana" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Subject: RE: [NGL-devel] ngl design concerning nglApplication (loonnng...) Message-ID: <[EMAIL PROTECTED]> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 In-Reply-To: <[EMAIL PROTECTED]> Sender: [EMAIL PROTECTED] Errors-To: [EMAIL PROTECTED] X-BeenThere: [EMAIL PROTECTED] X-Mailman-Version: 2.0.9-sf.net Precedence: bulk Reply-To: [EMAIL PROTECTED] List-Help: <mailto:[EMAIL PROTECTED]> List-Post: <mailto:[EMAIL PROTECTED]> List-Subscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Id: NGL developers discussion list <ngl-devel.lists.sourceforge.net> List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/ngl-devel>, <mailto:[EMAIL PROTECTED]> List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=ngl-devel> Date: Tue Aug 27 09:52:03 2002 X-Original-Date: Tue, 27 Aug 2002 18:48:20 +0200 > ... I'll try an explicit suggestion asap, I think I need to post this to > keep in sync.. > More to come... > > Lo. Well what I was thinking about is more or less what meeloo proposed (I leave that implicit for clarity) with some differences on the Entry Point issue : Exporting C++ classes from a dll is ok under win32.. I've done this and works fine... What i would try in order to avoid explicit declarations in main(), is something that relies on a template argument for the global class witch gives it a knowledge of the UserApp type and a variable (nested) virtual interface for Initialisation that the UserApp inherits in stead of inheriting the whole global object. One declares his UserApp & Instanciates the global object this way : (I'll try to stick to meeloo terminology) template <class UserAppType> class NGL_API nglApplicationKernel : private nglKernelBase { private: nglApplicationKernel (); // private constructor -> for singleton restrictions public : static int Run(int argc, char** argv) { int ret = -1; if (!instance) { gpKernelBase = new nglApplicationKernel<UserAppType>; UserAppType *pUserApp; pUserApp = new UserAppType; pUserApp->OnInit(); int ret = gpKernelBase->RunEventLoop(); pUserApp->OnExit(); delete pUserApp; delete gpKernelBase; } return ret; } class I_EntryPoint { virtual void OnInit() = 0; virtual void OnExit() = 0; virtual void OnIdle() = 0; // ... Some other pure virual interface methods ... }; }; where UserAppType must be at least : class UserApp : public nglApplicationKernel<UserApp>::I_EntryPoint { private: friend class nglApplicationKernel<UserApp>; // prevents instanciation from elsewhere than nglKernel. UserApp(){gpKernelBase->RegisterForEventLoop(this);} public: virtual void OnInit(); virtual void OnExit(); virtual void OnIdle(); }; the the setup macro would look like : #define NGL_APP_CREATE(UserAppType) \ int main(int argc, char** argv) \ { return nglApplicationKernel<UserAppType>::Run(argc,argv); } Et... Voila! Silly uh? ;p This is just an encapsulation solution, I think plugins will do as well with an adapted 'Run' method and accorded NGL_PLUGIN_CREATE macro. Cheers. Lo.