Migrating MDL Applications To Native Code


One of the new features of MicroStation V8 is the ability to build applications that are entirely Visual C based. This gives the advantage of using the native code debugger and other development tools. Most of these features have been possible for sometime by having little bits of MDL code that called the native code and kept things neatly seperated between MicroStation code and native code. Now all the callbacks are capable of being handled by native code implementations so the MDL layer disappears. You can convert your existing applications by following a few simple steps.

#define  DLLAPP_EXAMPLE  1
  DllMdlApp  DLLAPP_EXAMPLE =
  {
  "MDLNAME",  "dllname"
  }

Private MdlCommandNumber commandNumbers [] =
  {
  {commandFunctionName, CMD_MYCOMMAND_NUMBER},
  0
  }

Note that the 0 at the end is necessary to terminate the array.

Next you need to add to the main function a call to register the command numbers. For example:

mdlSystem_registerCommandNumbers (commandNumbers);

 

You need to change the signature of the main function to be

extern "C" DLLEXPORT int MdlMain (int argc, char *argv[])


This will make the main function visible to the mdl system. You then need to remove all the cmdName and cmdNumber lines in the source code. Since these are not standard C syntax they weill cause compile errors.

#define cmdName 1


then building a parallel structure to the commandNumbers:

Private MdlCommandName commandName[] = 
    {
    CommandNameFunction, "commandNamefunctionstring",
    0
    };

#------------------------------------------------ # Set up to use dlmlink.mki #------------------------------------------------  
dlmObjs     = $(o)$(AppName)$(oext)  \
               $(o)$(AppName)extra$(oext)

DLM_OBJECT_DEST     = $(o)
DLM_LIBDEF_SRC      = $(baseDir)
DLM_NAME            = $(AppName)
DLM_OBJECT_FILES    = $(dlmObjs)
DLM_NO_DLS          = 1  #  Used DLLEXPORT in .cpp file instead of using a .dls
DLM_NO_DEF          = 1
DLM_NOENTRY         = 1
DLM_DEST            = $(mdlapps)
DLM_LIBRARY_FILES   = $(mdlLibs)toolsubs.lib 

$(o)$(AppName)$(oext): $(baseDir)$(AppName).cpp

$(o)$(AppName)extra$(oext): $(baseDir)$(AppName)extra.cpp


#-------------------------------------------------------
#  Use dlmlink.mki to link the DLM.
#-------------------------------------------------------
%include dlmlink.mki

Note

There are multiple possible destinations for the app. Three common possibilities are:

DLM_DEST = $(mdlapps)
DLM_DEST             = $(mdlAsNeeded)
DLM_DEST             = $(mdlRequired)


Since there is no longer a .mc file to .mo file, this step this must be removed from the make file. And lastly, if the DllMdlApp resource was defined in a new resource file it needs to be added to the resources that are Rlib'd to make the application (.ma) file.

The application will now be compiled into a .ma and .dll. All the dialogs and user interface are still built as MDL resources but are fully accessible from the native code. To debug the application will require using the VisualStudio tools. To set the debug environment the dll needs to be added to the list of dlls by using the Project->Settings->category->additional dlls. After setting this you can use the Edit->Breakpoints command to add the function name to debug and establish a break point.

extern "C" DLLEXPORT
  #include <dlmpassw.h>
      MYAPP_PASSWORD


Some notes about this process:

Use of MicroStation built in variables:

extern UserPrefs *userPrefsP; 
extern  Tcb           *tcb;
extern  Mgds_modes    mgds_modes;
extern  int           mdlErrno;    /* mdl error number */
extern  MSStateData   statedata;


These are defined by including the msvar.fdf

malloc in the application should be replaced by dlmSystem_malloc this is so any memory allocated with the application can be freeed with the application. This will force all memory calls to be through the dlmSystem family of functions which will automaticly associate the resource allocation with the task id. This allows the memory to be reclaimed when the application exits. The complete list of functions is:

malloc -> dlmSystem_mdlMalloc 
calloc   ->  dlmSystem_mdlCalloc
realloc  ->  dlmSystem_mdlRealloc
free     ->  dlmSystem_mdlFree
strdup   ->  dlmSystem_mdlStrdup
fopen    ->  dlmSystem_mdlFopen
fclose   ->  dlmSystem_mdlFclose


Be aware of MDL code that might have been accessing functions using mdlDialog_callFunction Since this function was used to make function calls between MDL applications.  This function is not valid in the native code environment.

You cannot mix the use of DLS file and NO_DLS as defined in the Make file. The DLS file is used to create the export file, and is only necessary if you need to access the functions in the DLL from an MA. Thus it is usually not required, and generally preferable to use DLLEXPORT prefix for functions in the code. The prototype for mdlMain above takes this approach.

While MDL applications are still the core of MicroStation, moving source code to native code can allow the developer access to many features of the Windows development environment. This entire conversion process can take as little as one or two hours on a simple MDL application.