Welcome to MSDN Blogs Sign in | Join | Help

Invoking win32 GUI from posix code using mixedmode.

In the last post, i was talking about mixed-mode and the various scenarios that it enables. In this post, let us look at a small sample app that would make it more clear.

the goal of our sample app is to throw a win32 windows from posix code. There are two slightly different approaches that we can follow to do this.

1.      Use the win32 functions like registerclassex(), createwindow() etc in posix code

2.      Create a windows dll that exposes a function which uses registerclassex(), createwindow() etc to diplay a win32 window.

Though both these approaches are equally feasible from a technical standpoint, for the scenario at hand, I favor the second approach for more than one reason.

1.      We are going to call more than one win32 function, each of which takes and returns data whose type is alien to posix. Code would be better readable if we seperate win32 part and posix code

2. Creating windows, displaying content etc (for which we are going to use win32 functions) is logically a distinct piece. NOt lot o interecations are required by these win32 functions and posix code.  (to better understand this, cosider a database connectivity application. in such applications as database connectivity apps it makes a lot of sense to make direct win32 calls as the posix code would often process the data returned by the win32 call and make further win32 calls)

now that we have decided on the approach, we need to do two things

1.       build a dll that exports a function that would create a win32 window.

2.       link to the dll built in step 1 and call the exported function from posix code.

Step 1:

                This is ver straight forward. The only thing that one should be aware of is the datatypes that the exported function returns/accepts should be those that the posix code understands. For example if you were to export a function like the one below

                __declspec(dllexport) HANDLE drawwindow()

make sure that you define HANDLE in the posix part of the code. Alternatively, you can include the windows header file that defines the particular type in question. But this some times would result in header conflic/re declaration issues – more on this later.

    BOOL APIENTRY DllMain( HMODULE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                               )

{

      switch (ul_reason_for_call)

      {

      case DLL_PROCESS_ATTACH:

      case DLL_THREAD_ATTACH:

      case DLL_THREAD_DETACH:

      case DLL_PROCESS_DETACH:

            break;

      }

     

    return TRUE;

}

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

      switch (message)

    {

        case WM_DESTROY:

        PostQuitMessage (0);

        break;

        default:

        return DefWindowProc (hWnd, message, wParam, lParam);

    }

 

            return 0;

}

 

__declspec(dllexport) void drawwindow()

 {

      DWORD err = 0;   

      HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

      HWND hwnd;

      TCHAR szClassName[ ] = TEXT("WindowsApp");

    MSG messages;

    HACCEL hAccelTable;

     

      WNDCLASSEX wincl;

    /* The Window structure */

   

wincl.hInstance = hInstance;

    wincl.lpszClassName = szClassName;

    wincl.lpfnWndProc = WndProc;

      wincl.style = CS_HREDRAW | CS_VREDRAW;

    wincl.cbSize = sizeof (WNDCLASSEX);

    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);

    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);

    wincl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);

    wincl.cbClsExtra = 0;

wincl.cbWndExtra = 0;

wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))

            return;

      hwnd = CreateWindow(szClassName, TEXT("This is a Sample Window..."), WS_OVERLAPPEDWINDOW,

      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

 

      if (NULL == hwnd){

            err = GetLastError();

      }

      err = ShowWindow (hwnd, SW_SHOW);

      if(0 != err){

            err = GetLastError();

      }

 

      while (GetMessage (&messages, NULL, 0, 0)){

        TranslateMessage(&messages);

        DispatchMessage(&messages);

    }

 

    return;

 }

 

Build the above code as a dll

Step2:

                Now, write posix code that calls in to the dll built in step 1.

#include<pthread.h>

#include<stdio.h>

 

void* wrapper_drawwindow(void*);

extern void drawwindow(void);

 

main()

{

      pthread_t exThread = 0;

      printf("This is a POSIX Application!!!");

      fflush(stdout);

      pthread_create(

            &exThread,

            NULL,

            &(wrapper_drawwindow),

            NULL);

 

      pthread_join(exThread,NULL);

}

 

//this function calls drawwindow() which is exposed by windll.dll

void* wrapper_drawwindow(void* temp)

{

      drawwindow();

      return NULL;

}

 

Now build the above code as a mixed mode app

cc -R -o demo.exe SUA_WinUIDemo.c ./windll.lib

As I had said earlier, -R flag tells CC to build the app as a mixed-mode app. Windll.lib is the object file library of the dll that we built in step 1.

Run demo.exe and we have a posix application showing win32 gui.  I know the above sample doesn’t answer lot of questions. I’ll try to answer some questions like, how to resolve header conflicts, what form of IPC is possible in a mixed-mode app etc. If you have anything specific, do comment back.

 

Published Tuesday, February 06, 2007 7:36 PM by shankul
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Tuesday, April 15, 2008 1:36 PM by EddieH

# Cannot run mixed-mode with Win32 DLL in Vista Enterprise

We are looking at the feasibility of porting a set of applications that we currently build in Cygwin to SUA. We have been able to build monolithic executables using SUA and are able to debug these executables from within VS. Some of the apps, however, use the wxWidgets GUI toolkit which we have built as a DLL. We assumed that we would be able to make calls to this DLL from our SUA app in mixed mode. To date we have had no luck with this. We have looked at a simple HelloWorld app calling a simple HelloWorldDll, but as soon as we attempt to make any call into the Dll the app hangs at startup. We have tried your example above and get the same result.

We build from within VS2005 (ENU SP1) using the parameters that we round in the cc script (entry point of __MixedModeProcessStartup and the console subsystem). We have "Utilities and SDK for UNIX-based Applications_X86_RC1" installed on Windows Vista Enterprise Edition (No service pack because we do not have permission from our IT department to install it). We had to install the RC1 SDK to get debug to work on our monolithic apps.

Do you have any insight into what the issues might be here?

Tuesday, April 15, 2008 2:06 PM by shankul

# re: Invoking win32 GUI from posix code using mixedmode.

Eddie, does this work when you build that dll and app using CC/C89?

Lets take this conversation over to email.

Shanmugam.

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker