View previous topic :: View next topic |
Author |
Message |
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Tue Dec 14, 2004 2:18 pm Post subject: sample code so far |
|
|
For those who didn't see the sample I posted to the newsgroup, I've pasted it below. It runs on Windows and Linux (using Motif)
Code: |
import minwin.all;
version (Windows) {
import minwin.mswindows;
}
extern (C)
int MinWinMain(Application app) {
Frame frame = new Frame("Sample");
frame.quitOnClose = true;
frame.paintDelegate ~= delegate void (Component source, PaintContext* pc)
{
FontData fd;
fd.size = 80;
fd.weight = FontWeight.Bold;
Font f = new Font(&fd);
Font oldFont = pc.setFont(f);
pc.moveTo(100,100);
pc.drawText("Hello world");
pc.setFont(oldFont); // shouldn't forget or we'll delete a font in use
delete f; // if we forget it will eventually be garbage collected
}
version(Windows) {
// Windows wants the first window being shown to be
// passed the nCmdShow parameter.
// The nCmdShow property of Application is only defined on Windows
ShowWindow(frame.peer, app.nCmdShow);
} else {
frame.visible = true;
}
return app.enterEventLoop();
}
|
Comments welcome. |
|
Back to top |
|
|
Ant
Joined: 06 Mar 2004 Posts: 306 Location: Canada
|
Posted: Wed Dec 15, 2004 9:56 am Post subject: Re: sample code so far |
|
|
BenHinkle wrote: | the sample |
But, is this how the application code will look like?
Ant |
|
Back to top |
|
|
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Wed Dec 15, 2004 10:35 am Post subject: Re: sample code so far |
|
|
Ant wrote: |
But, is this how the application code will look like?
|
yes, but I don't expect many applications will want to paint on a frame. Instead the typical app will add widgets to the frame and only need to paint once in a while. I just wrote that example based on the winsamp.d sample that ships with D. What I'm working on now is adding button and message box support so that the rest of winsamp.d will work.
I'd like to avoid having MinWin do too much - the point is to wrap platform-specific GUI toolkits with the minimum amount of extra stuff and magic. |
|
Back to top |
|
|
Ant
Joined: 06 Mar 2004 Posts: 306 Location: Canada
|
Posted: Wed Dec 15, 2004 10:59 am Post subject: Re: sample code so far |
|
|
BenHinkle wrote: | Ant wrote: |
But, is this how the application code will look like?
|
yes, but I don't expect many applications will want to paint on a frame. Instead[... |
hmmm.... I don't like it.
Do you really think a D application should be concern with extern(C) and version(Windows) ?
Shouldn't those details be moved to the lib?
I'm guessing Frame is you MinWin class (otherwise ignore the following)
shouldn't Frame.visible be:
Code: | void visible(bit state )
{
version(Windows)
{
ShowWindow(frame.peer, app.nCmdShow);
}
else
{
// do the visible thing
}
} |
Ant |
|
Back to top |
|
|
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Wed Dec 15, 2004 1:12 pm Post subject: Re: sample code so far |
|
|
Ant wrote: |
Do you really think a D application should be concern with extern(C) and version(Windows) ?
Shouldn't those details be moved to the lib?
|
I'd like to remove the extern(C), that's true. It was the only thing I could get to work, though. The issue is that the WinMain defined in minwin.lib needs to find out what to call to start running user code. When I left MinWinMain as a D function it got mangled to include the module and so minwin.lib didn't know what to call. By declaring it as extern(C) minwin.lib calls MinWinMain (unmangled) and everything works. The same is true for the Linux main() code calling MinWinMain.
The version(Windows) part is something I want to keep since it really is special behavior on Windows. Simple applications can just ignore the nCmdShow and always to the frame.visible=true call without major issues. That way setting visible to true or false really does it. If Windows has a rule about the first time ShowWindow is called then I'd rather call that out in user code rather than add that special case to the library and hide it from the user (which will invariably lead to some confusion and debugging and much head-scratching).
Quote: |
I'm guessing Frame is you MinWin class (otherwise ignore the following)
shouldn't Frame.visible be:
Code: | void visible(bit state )
{
version(Windows)
{
ShowWindow(frame.peer, app.nCmdShow);
}
else
{
// do the visible thing
}
} |
|
It should use nCmdShow the first time and after that use SW_SHOWDEFAULT (or some variation on that) or SW_HIDE depending on state==true or state==false. |
|
Back to top |
|
|
Ant
Joined: 06 Mar 2004 Posts: 306 Location: Canada
|
Posted: Wed Dec 15, 2004 1:50 pm Post subject: Re: sample code so far |
|
|
BenHinkle wrote: | I'd like to remove the extern(C), that's true. |
There should be a way to do it. I can't imagine how.
Quote: | The version(Windows) part is something I want to keep since it really is special behavior on Windows. |
Still don't like it.
I would define a function that does nothing if not windows.
compiler optimizations will be able to not include the call to the function.
if the application start using version(system) then it's the application that
is cross platform, not the library.
Ant |
|
Back to top |
|
|
rr
Joined: 15 Dec 2004 Posts: 1
|
Posted: Wed Dec 15, 2004 2:16 pm Post subject: Agree with Ant |
|
|
A portable GUI should be exactly that. The whole point is to hide the platform differences from the programmer.
nCmdShow could be implemeted as a property of Frame, with a set default.equal on all platforms. And as Ant suggests, a funtion to change it that will only have effect on the Windows platform.
If you do not want such extra baggage in each frame, you might want to consider splitting into Main/AppFrame and Frame. IMHO
Roald |
|
Back to top |
|
|
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Wed Dec 15, 2004 2:35 pm Post subject: Re: sample code so far |
|
|
Ant wrote: |
Still don't like it.
I would define a function that does nothing if not windows.
compiler optimizations will be able to not include the call to the function.
If the application start using version(system) then it's the application that
is cross platform, not the library.
|
I believe wxWindows also has a special flag nCmdShow so it is taking the same approach I'm taking. Java ignores the whole issue. I don't know about other libraries. A special function that users call for the first time to show something makes *all* platforms worry about Windows behavior while just treating Windows specially is more reflective of the reality and is simpler.
Maybe I should refine a MinWin goal. Instead of saying it's a cross-platform toolkit (since I don't really believe true cross-platform toolkits exist), I'll start saying the following:
the goal of MinWin is to make multi-platform GUI development easier by providing a cross-platform base
For simple applications (like those that don't care about how to call ShowWindow the first time on Windows) the whole thing can be written in MinWin. |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Wed Dec 15, 2004 5:32 pm Post subject: Re: sample code so far |
|
|
BenHinkle wrote: |
I'd like to remove the extern(C), that's true. It was the only thing I could get to work, though. The issue is that the WinMain defined in minwin.lib needs to find out what to call to start running user code. When I left MinWinMain as a D function it got mangled to include the module and so minwin.lib didn't know what to call. By declaring it as extern(C) minwin.lib calls MinWinMain (unmangled) and everything works. The same is true for the Linux main() code calling MinWinMain.
|
Can't MinWinMain() be wrapped in an extern(C) function, such that the wrapper function is called by WinMain? That would get the extern(C) out of the application and into the library, no?
-John |
|
Back to top |
|
|
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Wed Dec 15, 2004 5:41 pm Post subject: Re: sample code so far |
|
|
JJR wrote: |
Can't MinWinMain() be wrapped in an extern(C) function, such that the wrapper function is called by WinMain? That would get the extern(C) out of the application and into the library, no?
|
I don't see how that would help. How would the MinWinMain call the user code? The reason for the extern(C) is to prevent name mangling so that the library can find the function to call.
Another option that occurred to me is to have the user code define a module initialization block that tells the library the entry point:
Code: |
static this() {
setMinWinEntryPoint(&foo);
}
int foo(Application app) { ... }
|
Then as long as the static block runs it should work out fine. It seems easier just to live with the extern(C), but it could be more flexible to have the static blocks. I'm not sure how wxWindows etc deal with this. |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Wed Dec 15, 2004 6:06 pm Post subject: |
|
|
Hmm... I must not be understanding the problem completely. I'd have to see the source to see what you are talking about. |
|
Back to top |
|
|
saivert
Joined: 15 Aug 2005 Posts: 8 Location: Norway
|
Posted: Tue Aug 16, 2005 4:18 am Post subject: D Linkeage. |
|
|
Isn't the LIB compiled with D anyways?`Then It should have access to other code with D linkage withouth problems with mangling. If both the LIB and the app itself has D linkage then they should speak the same language I mean. Maybe D compiler needs to have a fix.
This at least works with C++ functions. A c++ lib can call a c++ function in another C++ lib.
And A D lib should be able to call a D function in another D lib. _________________ - New at D, like it though - Attending Kongsberg Tekniske Fagskole (Computer technician course) - |
|
Back to top |
|
|
BenHinkle
Joined: 27 Mar 2004 Posts: 76
|
Posted: Thu Aug 18, 2005 2:58 pm Post subject: |
|
|
The issue is that D adds the module name as part of the name mangling. So that means the MinWin library needs to know the module that contains the main() if it is gong to use D name mangling. By using extern(C) the name mangling is turned off and the library calls _MinWinMain. If it weren't for the module name I agree it would be able to link and run just fine. |
|
Back to top |
|
|
svanleent
Joined: 25 Sep 2004 Posts: 53
|
Posted: Sun Oct 09, 2005 4:11 am Post subject: |
|
|
I think I get the problem here.
Let's look at the main() function D is able to use. You see, everywhere the main function can be declared because the compiler creates a prologue which calls that main function, therefor the name mangling problem is no issue. However, within this application, name mangling is a problem.
For a MinWin application, as I understand, another function has to be called. The suggestion of "hinting" the library with an initialization function seems feasible indeed, also, this way, some configuration parameters can be exposed to the library, so:
Code: |
module x.y.z;
import minwin;
static {
minWinStart = &start;
. . . configuration . . .
}
int start() {
. . .
}
|
This way, it should be possible to configure minwin and no problems should exists with externalized functions.
Regards,
Sjoerd _________________ How C++ became ancient |
|
Back to top |
|
|
|