digitalmars.com                        
Last update Sun Mar 4 11:58:08 2018

Porting Guide

This chapter lists and describes compiler and/or linker errors and other problems that can occur when porting existing code to Digital Mars C++.

What's in This Chapter

General tips on porting to Digital Mars C++

This section provides tips on how to solve problems that might occur when porting code to Digital Mars C++ that was written with another compiler, or with a previous release of Digital Mars C++ or Zortech C++. For related information, see Switching to Digital Mars C++.

Problem: iostreams library incompatible with -Ju

The Digital Mars C++ Version 7 iostreams library is incompatible with code compiled with the -Ju compiler option; syntax errors and link errors result. This is because, when you specify -Ju, the compiler treats char and unsigned charas the same type. This can cause distinct functions to appear to be the same, and can make mangled names different from the corresponding names in the iostreams library.

Here are two recommended solutions:

Problem: Linker error "EXE header > 64k"

This error results if your code exports too many names. If names in a DLL are not referenced by name at run-time using the Windows API function GetProcAddress(), you can specify the /BYORDINAL and /NONAMES linker options, which remove all names from the DLL header and use the corresponding ordinal numbers instead.

Problem: GetProcAddress() fails

If you are exporting names by ordinal value (see above), no names are included in a DLL, and a call to GetProcAddress() with the name of the procedure will fail. This can also result in problems at link time and load time. Here are two recommended solutions:

Problem: Unsupported build steps

Your .MAK or .BAT files may contain build steps that the Digital Mars C++ IDDE does not support. For example, a makefile might call an SQL preprocessor that emits C code. The SQL code would need to be processed before the IDDE compiles the C files. You can solve this problem by adding a .MAK file to the Digital Mars C++ project. Put it before the compile step in the IDDE's Build Order list box. Then make a target "clean" (which should not be the first target); "clean" will be built when you rebuild the entire project. Note that the first target will be built in the makefile directory; "clean" will be built in the project directory.

Problem: Linker error "DGROUP + Stack + Heap exceeds 64k-16"

The data segment of a 16-bit program can only be 64K bytes long. The combined data definitions of all your modules has exceeded this threshold. To solve this problem, check the "Set Data Threshold" check box on the Code Generation subpage of the Build page in the IDDE's Project Settings dialog box (or use the -GT1 compiler option). This directs the compiler to place data objects larger than the specified size in their own far data segments. Setting the size to 1 puts all data objects in individual data segments.

Problem: Moving a project "loses" the libraries

In this case, the compiler cannot find libraries after you move an existing IDDE project to a new directory. When you add a library in the \dmc\lib directory to a project, do not specify a path. This prevents the IDDE from assigning the library a path that is relative to the project directory.

Problem: Path problems in sc.ini

If you specify the include path for your project in sc.ini, non-Digital Mars tools that rely on the definition of the INCLUDE environment variable for path information cannot access the information. Use autoexec.bat, the Windows NT Registry, or the project include directory setting instead.

Problem: Path problems in autoexec.bat

If you specify the include path for your project in autoexec. bat, you need to restart Windows in order to change it, and the information will not be used for Windows NT builds. Use sc.ini, the Windows NT Registry, or the project include directory setting instead.

Problem: Path problems with project include directory setting

If you specify the include path for your project in the IDDE's "Project include directory" setting, non-Digital Mars tools cannot access the information, and it will be specific to that project only. Use autoexec.bat, the Windows NT Registry, or sc.ini instead.

Problem: Path problems in NT Registry

If you specify the include path for your project in the Windows NT Registry, you won't be able to change it via a batch file, and it won't be available for Windows 3.1 builds. Use autoexec.bat, the project include directory setting, or sc.ini instead.

Problem: 16-bit programs with virtual functions crash

In this case, programs that use classes that define virtual functions cause General Protection Faults. For example, an executable defines a class with virtual functions, and the virtual functions are called by DLLs. This happens because executables with virtual functions must have "smart callbacks" set; otherwise, the function will be invoked with the wrong value for DS. (In the IDDE, click the "Load DS from SS" button in the Windows Prolog/ Epilog subpage of the Build page of the Project Settings dialog box.) For more information, see Win16 Programming Guidelines.

Problem: You need generic .MAK files

To create generic makefiles that can be called from different projects, get the name of the calling project from the predefined identifier MASTERPROJ.

Problem: You need to link with a DLL at link time only

To link an EXE or DLL with another DLL at link time only:

Problem: You need to link with a DLL at run-time only

To link an EXE or DLL with another DLL at run-time only:

Tips on porting from Microsoft Visual C++

This section provides tips on how to solve problems that might occur when porting code to Digital Mars C++ from Microsoft Visual C++. For related information, see Converting from Microsoft.

Problem: _ExportedStub missing

The Microsoft C++ libraries provides the entry point _ExportStub, which can be exported by user .DEF files. Remove _ExportStub from your .DEF files; it is specific to Microsoft's implementation of its internal routine _GetGROUP. This change is unlikely to introduce any problems.

Problem: WIN32 and _X86_ not defined

32-bit versions of Microsoft C++ provide a .MAK file that defines -DWIN32= 1 and -D_ X86_= 1. Digital Mars C++ does not provide this file. Digital Mars C++ defines these macros in the header file SCDEFS.H, which is included whenever you include a Win32 API header file. If you are not using the Win32 API, you can explicitly include SCDEFS.H, or define WIN32 and _X86_ on the compiler command line or with the IDDE.

Problem: overloaded functions produce errors

Microsoft C++ (and Borland C++) do not distinguish between overloading of int and unsigned short. Digital Mars C++ does, and generates an error for each ambiguous reference. For example:
void f(unsigned short);
void f(int);
void main ()
{
  short s;
  f(s);
}
In Digital Mars C++, s can be promoted to either int or unsigned short, whereas Microsoft C++ always calls f(int). Problems in user code can be due to one function being declared in two slightly different ways, so that it looks like two different functions to Digital Mars C++. For example:
void f(WORD);   // Later on in different #include'd file
void f(int);    // Looks like different C++ function

Problem: _MT not automatically defined

32-bit Microsoft C++ sets _MT=1 if the /MT (multi-threaded) option is specified. If /MD (multi-threaded DLL) is specified, 32-bit Microsoft C++ sets _MT=1 and _DLL=1. Digital Mars C++ has no equivalent switches because its 32-bit run-time library is always multi-threaded. To solve this problem, define _MT and _DLL on the dmc command line as necessary.

Tips on Porting from Borland C++

This section provides tips on how to solve problems that might occur when porting code to Digital Mars C++ from Borland C++ Version 3. For related information, see Converting from Borland.

Problem: _DEFS.H

Borland C++ provides a file BC\ INCLUDE\_ DEFS.H, which their STDIO.H library includes. This file contains a number of definitions used in Borland header files; these definitions might also appear in user code. Although Digital Mars C++ does not provide equivalent definitions, you can explicitly include Borland's _DEFS.H in your Digital Mars C++ compilation. This is unlikely to introduce any problems.

Problem: const * to non-const * conversion

Borland C++ permits implicit conversions between const * types and non-const * types. Digital Mars C++ does not permit this. For example:
const char *p;
char *q;
q = p;  // causes "cannot implicitly convert"
        // error in DMC++
Add explicit casts as necessary to add or remove const-ness An easy way to eliminate const-ness problems is to add this code:
#define const

Problem: signed * to unsigned * conversion

Borland C++ permits implicit conversions between signed * types and unsigned * types. Digital Mars C++ does not permit this. For example:
unsigned int *p;
int *q;
q = p;  // causes "cannot implicitly convert"
        // error in DMC++
Add explicit casts as necessary to add or remove signed-ness.

Problem: int to pointer conversion causes errors

Borland C++ allows ints to be converted to pointers with only a warning. This is an error in Digital Mars C++. To fix this error, explicitly cast or convert ints to pointers as appropriate.

Problem: overloaded functions produce errors

Borland C++ (and Microsoft C++) do not distinguish between overloading of int and unsigned short. Digital Mars C++ does, and it generates an error for each ambiguous reference. For example:
void f(unsigned short);
void f(int);

void main()
{ short s;
  f(s);
}
In Digital Mars C++, s can be promoted to either int or unsigned short, whereas Borland C++ always calls f(int).

Problems in user code can be due to one function being declared in two slightly different ways, so that it looks like two different functions to Digital Mars C++. For example:

void f(WORD);   // Later on in a different #include file...
void f(int);    // Looks like a different C++ function

Problem: const-ness of overridden functions

Borland C++ allows a function of a derived class to have different const-ness from the same function in the base class, in violation of ARM 10.2. For example:
class A {virtual int f(void);};
class B: public A {
    const int f(void);  // DMC++ generates "name previously declared
                        // as something else" error
};
To solve this problem, rewrite your code to make the const-ness of functions in derived classes match that of their base class equivalents.

Problem: Definition of max and min macros for C++

The Borland C++ windows.h header file does not define the macros max and min for C++. The Digital Mars C++ version of windows.h defines these macros.

Here are two recommended solutions:

Problem: Inclusion of windows.h in resource files

The Borland IDE implicitly includes windows.h in any .RC file it compiles. The Digital Mars IDDE does not. Therefore, you need to explicitly add the code #include <windows.h> to .RC files.

Problem: Redefinition of default arguments

Borland C++ allows redefinition of default arguments (in violation of ARM 8.2.6). For example:
int f(int i = 0);
int f(int i = 0);       // DMC++ gives error
Remove the second default definition. For example:
int f (int i = 0);
int f (int i);

Problem: Automatic enum conversions

Borland C++ provides an option to "treat enums as ints." Digital Mars C++ does not allow implicit conversions of ints to enums, or implicit conversion of enums to other enums in C++ compilations. For example:
enum color (black, red, green, blue);
enum color current_color = NULL;        // DMC++ error
There are two recommended solutions:

Problem: Undefined escape cequences

Borland C++ ignores undefined escape sequences in strings. For example, it interprets \U as U. Digital Mars C++ generates an error in this case. To avoid the error, remove unnecessary escape characters (\) from strings.

Problem: Return types for constructors/destructors

Borland C++ allows a return type for constructors and destructors (in violation of ARM 12.1 and ARM 12.4). Digital Mars C++ does not allow this. For example:
void A::A() {...}       // DMC++ generates "illegal constructor
                        // declaration" error
Remove the return type from the declaration. For example:
A::A() {...}

Problem: Differentiating functions by addressing or calling conventions

Borland C++ differentiates between two functions with the same name in a class if they have different addressing or calling conventions. Digital Mars C++ does not. For example:
class x
{
    void func();
    void __far__ pascal func (); // DMC++ generates "function is already
                                // defined" error
};
The problematic declaration is most likely a mistake; remove the additional declaration.

Problem: No implicit function declarations for derived classes

Borland C++ allows functions to be defined for a derived class that were only declared for the base class, not the derived class. For example:
class A
{ public:
    virtual void f() = 0;
};

class B: public A {};

void B::f()     // DMC++ generates "function is
                // not a member of class" error
{...}
Put explicit declarations for all of a class's functions in the class declaration. For example:
class B: public A
{
  public:
    void f();
};

Problem: findfirst() and findnext()

The Borland versions of the functions findfirst() and findnext() take different parameters from their Digital Mars counterparts. Rewrite your code to use the Digital Mars versions of findfirst() and findnext(), or use _dos_findfirst() and _dos_findnext(). For information see the Digital Mars C++ Runtime Library Reference.

Problem: _control87() parameters

Borland C defines various constants for use as parameters to the _control87() function (MCW_EM, EM_INVALID, EM_DENORMAL, and so on), whose names differ from their Digital Mars equivalents. You can form the equivalent Digital Mars C constants by adding an underscore (_) to the Borland version; for example: _MCW_EM or _EM_INVALID.

Problem: __DLL__ macro defined for DLL compilations

Borland C defines the macro __DLL__ for DLL compilations; Digital Mars C does not. Here are two recommended solutions:

Problem: undefined type dosdate_t

The type dosdate_t declared in Borland C's dos.h file is not defined in Digital Mars C. Change all instances of dosdate_t to _dosdate_t.

Problem: no values.h file

Borland C provides a file values.h, which defines various implementation defined limits (for instance, MAXINT, which represents the largest int). Digital Mars C does not provide an equivalent file. You can use the ANSI standard file limits.h instead. To do this, you will need to change the names of most of the defined identifiers (MAXINT is called INT_MAX, for instance).

Problem: Typos in long identifiers

Borland C uses the first 32 characters in identifiers; Digital Mars C uses the first 254. This can expose typing errors at the ends of long identifiers. For example:
#define I_am_not_very_happy_monday_morning 1
i = I_am_not_very_happy_monday_mornings;
// BC does not generate an error; dmc does
Fix any typing errors as needed.

Problem: _argc and _argv not declared

Borland C declares the variables _argc and _argv in dos.h. Digital Mars C++ does not. Add the following declarations as needed:
extern int __cdecl _argc;
extern char ** __cdecl _argv;
Note that these names are not part of the published Digital Mars C/C++ run-time library interface, and are subject to change.

Problem: Invalid bitmap syntax

The resource compiler run from the Borland IDE accepts an alternate syntax for BITMAPs, where the actual bitmap is specified in the code rather than in a file. For example:
Example BITMAP
BEGIN
    '42 4D 5E 00 ...
Digital Mars's rcc and Microsoft's rc do not accept this syntax. Use Borland's Resource Workshop to convert the text to a .BMP file and change the code to:
Example BITMAP .BMP

Problem: Invalid pointer conversions

Borland C allows conversion of different pointer types with only a warning. Digital Mars C++ does not. For example:
void f()
{   int *p;
    char **q;
    q = p;      // dmc generates error "cannot implicitly convert"
Examine your code for correctness, and add explicit casts where appropriate.

Problem: Names declared in different header files

Some names that are defined in both Digital Mars C++ and Borland C++ are declared in different header files. An example is the run-time library function coreleft(), which is declared in stdlib.h in Digital Mars C++ and alloc.h in Borland C++. To fix this problem, change the header files that your code includes as appropriate.

Problem: Automatic definitions

Borland C allows an extern variable to be declared without ever being explicitly defined. In Digital Mars C++, this results in the error "symbol undefined:< symbol>" at link time. For example, where the following is a complete program:
extern int a;
void main() {a = 1;}
Add explicit definitions to your code as required.

Problem: Names referenced in .ASM files

Borland C++ mangles only function names. Digital Mars C++ mangles both function and variable names. This can cause link errors on names referenced in .ASM files. For example: extrn _a: word produces a link error in DMC++ because the correct name is ?a@@3HA.

There are two recommended solutions:

Problem: Inconsistencies in declarations at link time

Borland C++ only mangles the names of variables slightly. For example, for function pointers it does not encode the parameters of the function; Digital Mars C++ does. This can expose inconsistencies in declarations at link time.

Make declarations consistent where needed.

Problem: Inconsistencies in _pascal declarations at link time

Borland C++ does not encode the _pascal calling convention modifier into mangled names (except by making the mangling all lowercase); Digital Mars C++ does. This can expose inconsistencies in declarations at link time for case-insensitive links.

Make declarations consistent where needed.

Problem: opendir, closedir, etc. not available

The Borland library functions opendir, closedir, readdir, and rewinddir functions are not available in Digital Mars C++.

Rewrite your code to use _dos_findfirst, _dos_findnext, or findfirst/ findnext(). For information, see the Digital Mars C++ Run-time Library Reference.

Problem: Linker cannot export names

If the Digital Mars linker cannot find names listed in the project .DEF file's EXPORT list, one of these issues is the cause:

Problem: Undefined Borland identifiers in .RC files

Some Borland predefined identifiers, like IDHELP, are undefined when you compile resources with Digital Mars's rcc.

Borland's resource compiler automatically includes bwcc.h, so you need to explicitly include bwcc.h in the .RC file.

Problem: BC program does not load after conversion to dmc

If this is your problem, you might find that one or more DLLs do not load, or "undefined dynalink" errors occur.

Make sure that all Digital Mars compiler options match their Borland equivalents. For example, exports can be uppercase, by ordinal, export all far, and so on.

Problem: BC program does not run after conversion to dmc

If a Borland program compiles but does not run, check that all Digital Mars compiler options match their Borland equivalents. For example, Borland's default struct alignment is on byte boundaries, Digital Mars's is on word boundaries.

Problem: _new_handler is not declared

Borland C++ declares pvf _new_handler in the file new.h. Digital Mars C++ does not.

Simply add the declaration _PNH _new_handler as needed.

Problem: _new_handler behavior is different

Borland's _new_handler function takes no arguments, and exits on failure. Digital Mars's _new_handler takes one argument (the number of bytes to make available) and returns zero on failure.

Simply recode calls to _new_handler as needed.

Problem: "class huge" syntax not supported

Borland C++ allows the keyword huge after class in a class declaration. Digital Mars C++ does not. For example:
class huge A;
Rewrite any class declarations that use the huge keyword.

Problem: Non-Pascal names not found at DLL load time

Windows cannot find exported names in a DLL if they are lowercase. Borland's IMPLIB solves this problem by always exporting names in DLLs by ordinal. Digital Mars's linker does not automatically do this; therefore, some non _pascal names might not be found when a DLL is loaded.

Link with these Digital Mars linker options: /XUPPER (Export, uppercase) and /BYORDINAL (Export by ordinal).

Problem: Can't convert between unsigned char and char

The Borland C++ option -K makes unsigned char and char the same type.

Try one of these two possible solutions:

Tips on porting from previous Digital Mars releases

This section provides tips on how to solve problems that might occur when porting code from previous releases of Digital Mars C++ or Zortech C++. For related information, see Switching to Digital Mars C++.

Problem: asm() function does not compile

Zortech C++ allowed instructions to be assembled from integers using the asm() pseudo-function. For example:
asm (0x8C, 0x96, 0xCC, 0xFE);
Digital Mars C++ does not provide this function. Therefore, you need to replace asm() calls with calls to __emit__. For more information, see Using Assembly Language Functions.

Problem: ios class not declared in iomanip.h

Previous versions of the iostreams library declared the ios class in iomanip.h. The current version of iostreams does not.

You need to explicitly include iostream.h.

Problem: Zortech library names are different

Zortech C++ library names specified in makefiles are different from the corresponding Digital Mars C++ names (ZWL corresponds to SWL, for example).

Change your makefiles to use the Digital Mars C++ library names. Note that, since the names of libraries are specified in object files, it may not be necessary to explicitly specify them in the makefile.

Problem: Compiler control program has a different name

The Zortech C++ compiler control program was ZTC.EXE. The Digital Mars C++ equivalent is dmc.

Change makefiles, batch files, and so forth to run dmc instead of ZTC.

Problem: Missing #endifs generate errors

Zortech C++ allowed #endif directives at the end of files to be omitted; it interpreted End of File as any number of #endifs. Digital Mars C++ does not.

Add #endif directives to the ends of files as appropriate.

Problem: __pascal names mangled in C++ files

Zortech C++ did not perform C++ name mangling on __pascal names. In Digital Mars C++, the __pascal modifier changes the calling sequence, but does not affect name mangling.

Add the modifier extern "C" to declarations that should not be mangled. For more information, see Mixing Languages.

Problem: Jumps around variable initializations disallowed

Zortech C++ allowed jumps around variable initializations, in violation of ARM 6.4.2. Digital Mars C++ does not allow this. For example:
switch (i)
{
    int v1 = 2; // error
  case 1:
    int v2 = 3;
  case 2:
    if (v2 == 7) // error
        ...
There are two recommended solutions for this problem:

Problem: Differences in mangled names

Zortech C++ code might not link with Digital Mars C++ because .ASM files reference mangled names. The Digital Mars C++ name mangling scheme differs from Zortech C++ name mangling.

Use the obj2asm utility to obtain the new mangled names, and manually edit the assembly language files to use these names. For information on Digital Mars C++ name mangling, see Mixing Languages.

Problem: WEP in user code causes a link error

Digital Mars C++ Version 6 allowed users to specify a WEP function in a DLL. Digital Mars C++ Version 7 provides a WEP function in the library, which handles static destructors and other cleanup functions on exit from the DLL. Thus, WEP functions should not be used if these function are required.

If a DLL requires special termination procedures, put them in a function called _WEP. Digital Mars's WEP automatically calls _WEP. An _WEP function is not required, however.

Problem: Access to protected members not allowed

Zortech C++ allowed access to protected member functions, in violation of ARM page 253. (Base class members can only be accessed through a derived class.) For example, the following is an error in Digital Mars C++:
class A {protected: int x };
class B: public A
{
  void f() {
    x = 10;
  }
  void f1() {
    A *p = new A; p-> x = 10; // error
  }
  friend void f2(A*);
  friend void f3(B*);
};

void f2(A* a) { a->x = 10; } // error
void f3(B* b) { b->x = 10; }
To solve this problem, recode invalid constructs as necessary.

Problem: Mismatches in C++ const functions not allowed

Zortech C++ allowed mismatches in function declarations involving const-ness. For example, the following constructs, which were valid in Zortech C++, are invalid in Digital Mars C++:
class A
{ public:
    int operator== (A&);
};

class B
{   A a;
    int operator==(B& b) const
    {
      return (a == b.a); // error in DMC++ 7
    }
};
In the above example, since B::operator== is const, B::a is const, but there is no matching function in A. To fix the error, you need to add the required matching function. To fix the example code above:
class A
{ public:
    int operator==(A&);
    int operator==(A&) const;
};

Tips on porting Win16 Code to Win32

This section provides tips on how to solve problems that might occur when porting 16-bit Windows 3.1 code to a 32-bit Windows environment. See Win32 Programming Guidelines, for general information on porting 16-bit code to Win32.

Problem: Files not found when porting to Windows NT

Symptoms of this problem include .MAK or .BAT files generating errors, or programs not finding files.

Windows NT does not run the autoexec.bat file, so your PATH environment variable (and other environment variables) may not be set. You need to manually add these values to the Windows NT Registry.

Problem: 32-bit SmartHeap does not work

In this case, SmartHeap symbols are not found when linking with 32-bit SmartHeap libraries (specifically SHDW3SMD.LIB).

The version of SHDW3SMD.LIB shipped with SmartHeap is not usable. To create a usable one, perform this step to create a new library directly from the SmartHeap DLL:

implib /system shdw3smd.lib sh22w3sd.dll

Problem: Windows 3.1 functions undefined at link time

Some Windows 3.1 routines, such as GetCurrentTask(), are obsolete for Win32.

You need to reengineer these routines. For information, see Microsoft Win32 API Programmer's Reference (available as the online Help file ..\dm\help\vc20bks4.hlp in Digital Mars C++).

Problem: ToolHelp functions undefined at link time

The Windows 3.1 ToolHelp library, which includes functions like ModuleFindHandle() and StackTraceNext(), is not available in Win32.

You need to reengineer these routines. For information, see Microsoft Win32 API Programmer's Reference (available as the online Help file ..\dm\help\vc20bks4.hlp in Digital Mars C++).

Problem: Exported names not found

If this is a problem, the linker indicates that it cannot export any of the names in the .DEF file's export list, although the export list worked for Windows 3.1.

Win32 defines PASCAL, WINAPI, and related functions as __stdcall; in Windows 3.1 they were defined as __pascal. This means that all PASCAL/ WINAPI functions now begin with an underscore (_) and are case-sensitive. Add underscores and change case in the export list as needed.

Problem: Names in .ASM files not found

If this is a problem, the linker indicates that it cannot fnd PASCAL names that are declared in .ASM files, although it could for Windows 3.1.

Win32 defines PASCAL as __stdcall; in Windows 3.1 it was defined as __pascal. __stdcall functions begin with an underscore (_) and are case-sensitive. Add underscores and change case in the assembly language definitions of the affected functions.

Problem: DOS functions undefined in NT compilations

An example would be int86x and its parameter, union REGS, being undefined in a Windows NT compilation.

Some DOS routines may need to be re-engineered using their Windows NT equivalents. For information, see Microsoft Win32 API Programmer's Reference (available as the online Help file ..\dm\help\vc20bks4.hlp in Digital Mars C++).

Problem: "FIXUPP" errors in 32-bit links

In this case, the linker generates an error for every reference to an external name in the build.

You may be using outdated linker options. The Digital Mars C++ IDDE uses: /DO/DE/NT/Entry:__DllMainCRTStartup.

Problem: Assembler files don't link in Win32

In this case, assembly language code with .286 or 16-bit segments may not link.

Recode affected files to remove 16-bit specific features. Note also that the use of segment registers is different for Win32 compilations.

Problem: 32-bit link errors

In this case, you might need to convert your .DEF file to 32-bit. The Digital Mars C++ IDDE uses EXETYPE NT, no STUB, CODE SHARED EXECUTE DATA WRITE, and HEAPSIZE 100000,4096.

Problem: Undefined resource symbols in Win32 links

To solve this problem, compile 32-bit resources for 32-bit links with the command rcc -32.
Home | Runtime Library | IDDE Reference | STL | Search | Download | Forums