TABLE OF CONTENTS ~~~~~~~~~~~~~~~~~ 1. Getting started 1.1 Compilation process 1.2 Linker module definition file 1.3 Target platforms 1.4 OS/2 API interface units 2. Borland Pascal compatibility issues 2.1 Data types 2.2 Pointer types 2.3 Integer expressions 2.4 Standard unit implementation differences 2.4.1 System unit 2.4.2 Dos unit 2.4.3 WinDos unit 2.4.4 Crt unit 2.4.5 WinCrt and Strings unit 2.4.6 32-bit Turbo Vision for OS/2 2.5 Compiler directives 2.6 Built-in assembler 2.7 Register usage 2.7.1 Embedded ASM statements 2.7.2 Assembler procedures and functions 2.8 Code generation differences 2.9 Import and export 2.10 Inline statements and inline subroutines 3. New Virtual Pascal features 3.1 Calling conventions 3.2 Naming convention 3.3 Pure interface units 3.4 Direct port access 3.5 Import 3.6 Export 3.7 Presentation Manager resources 3.8 Writing OS/2 Dynamic Link libraries 3.8.1 Subroutine libraries 3.8.2 Subsystems 1. GETTING STARTED ~~~~~~~~~~~~~~~~~~ There is no documentation in this beta release other than online help system of the IDE and this file. This documentation is addressed to those who are familiar with Borland Pascal. If you are a user of the Borland Pascal, you may have only few problems, because VP and BP are very much alike. Even error messages have the same numbers and spellings. This document reflects the main differences between Virtual Pascal and Borland Pascal v7.0 and introduces new Virtual Pascal features. 1.1 COMPILATION PROCESS ~~~~~~~~~~~~~~~~~~~~~~~~ Borland Pascal compiles source code to the object code with a compiler version and target platform specific format. For a unit it generates .TPU/.TPP/.TPW files (.DCU in Delphi Pascal Compiler) that contains object code and interface symbol information. Virtual Pascal generates two kind of files: - containing object code (.OBJ, .LIB or ASM); - containing interface symbol information (.VPI). The following picture describes the compilation process: ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄ>Ä´ UnitName.OBJ ³ $SmartLink- ³ ³ UnitName.VPI ³ $Asm- ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ UnitName.OBJ ³ $SmartLink- ³ UnitName.PAS ÃÄÅÄÄÄÄÄÄÄÄ>ij UnitName.ASM ³ $Asm+ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ UnitName.VPI ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ UnitName.LIB ³ $SmartLink+ ÀÄÄÄÄÄÄÄÄ>ij UnitName.VPI ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ProgramName.OBJ ³ ³ ProgramName.PAS ÃÄÄÂÄÄÄÄ>Ä´ ProgramName.ASM ³ $Asm+ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ProgramName.LNK ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÀÄÄÄÄ>Ä´ ProgramName.OBJ ³ $Asm- ³ ProgramName.LNK ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ LibraryName.OBJ ³ ³ LibraryName.PAS ÃÄÄÂÄÄÄÄ>Ä´ LibraryName.ASM ³ $Asm+ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ LibraryName.LNK ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÀÄÄÄÄ>Ä´ LibraryName.OBJ ³ $Asm- ³ LibraryName.LNK ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ .ASM file is a readable 386 assembly source file which can be compiled by MASM 6.0a+ or TASM 3.0+. .OBJ and .LIB files are standard Intel Object Module Format (OMF) object and library files. They can be linked by any 32-bit OMF linker, which is capable of generating linear executables (LX) for OS/2. By default, Virtual Pascal uses LINK386 supplied with OS/2. Note, that if a unit has no code (it is simply used to define constants and types), then no object code is generated and there would be no .OBJ or .LIB file for it. .LNK file is a linker response file which should be passed to the linker. It contains the list of object and library files, module definition file name (if compiler found it) and linker map file name (VPC: if /G command line option is specified, IDE: Linker³Map file active button is other than None). .VPI file is a Virtual Pascal Interface file. It contains interface symbol information. Only .VPI file format is compiler version dependent. For directions of how to distribute object code without source, see PURE INTERFACE UNITS section. 1.2 LINKER MODULE DEFINITION FILE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Borland Pascal has a built-in linker, that is why it passes additional information (segment attributes, description text, etc) to the linker by means of compiler directives. Virtual Pascal uses standalone linker, so you can use linker module definition file to supply this additional information about your application. You must use module definition file to create dynamic link libraries. Module definition file should be located in the same directory as a primary file of the program or library, and must have the same name, but a .DEF extension. A module definition file is a plain text file that describes the names, segment attributes, exports, imports, and other characteristics of an application or library. It contains one or more module statements. Here are the brief summary of the module statements: BASE = BaseAddress CODE [PRELOAD | LOADONCALL] [EXECUTEONLY | EXECUTEREAD] [IOPL | NOIOPL] [CONFORMING | NONCONFORMING] DATA [PRELOAD | LOADONCALL] [READONLY | READWRITE] [NONE | SINGLE | MULTIPLE] [SHARED | NONSHARED] [IOPL | NOIOPL] DESCRIPTION 'text' EXETYPE OS2 EXPORTS ExportName [= InternalName][@Ordinal][RESIDENTNAME | NONAME] [StackParams] IMPORTS [InternalName =] ModuleName.EntryName | ModuleName.Ordinal LIBRARY [LibraryName] [INITGLOBAL | INITINSTANCE] [TERMGLOBAL | TERMINSTANCE] NAME [ApplicationName] [WINDOWAPI | WINDOWCOMPAT | NOWINDOWCOMPAT] OLD `filename.DLL' SEGMENTS ['] Name ['] [ CLASS ['ClassName']] [PRELOAD | LOADONCALL] [READONLY | READWRITE] [EXECUTEONLY | EXECUTEREAD] [IOPL | NOIOPL] [CONFORMING | NONCONFORMING] [SHARED | NONSHARED] STUB `FileName.EXE' | NONE 1.3 TARGET PLATFORMS ~~~~~~~~~~~~~~~~~~~~ Virtual Pascal can generate code for either OS/2 full screen application or Presentation Manager application. Virtual Pascal combines all three Borland Pascal target platforms into one. You should specify the type of the application to be generated by the Linker³Application radio buttons or specify application type in the NAME statement of the module definition file (if you use linker other than LINK386). 1.4 OS/2 API interface units ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is a good practice to use standard Borland Pascal unit procedures and functions for your programs. If you need OS/2 specific functions you can use OS/2 API interface units to call them directly. There are four interface units supplied: Os2Def: Contains common definitions for OS/2 base and Presentation Manager API. Os2Base: Contains API functions and type declarations for writing OS/2 base applications. It also contains 16-bit API function prototypes for writing full screen applications (KBD/VIO/MOU/MON/NLS calls). Os2PmApi: Contains Presentation Manager interface constants, types and function prototypes. Os2Rexx: Contains an interface to OS/2 REXX interpreter. 2. BORLAND PASCAL COMPATIBILITY ISSUES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unlike Borland Pascal, Virtual Pascal generates 32-bit code. The main differences between Borland Pascal and Virtual Pascal are due to this fact. To maintain backward 16-bit compatibility, Virtual Pascal uses some tricks described in this chapter. 2.1 DATA TYPES ~~~~~~~~~~~~~~ All built-in data types have the same name, size and meaning, except for two floating point types (Real and Extended). Virtual Pascal uses only coprocessor types, that is why Real and Double types are identical. Extended type is 10-byte floating point coprocessor type, but occupies 12 bytes to maintain double word alignment. Built-in assembler accepts 12-byte sized variables as TBYTE operands. It is not efficient to use on true 32-bit processor 16-bit integer variables. That is why to maintain backward 16-bit compatibility, in 32-bit programs written in Virtual Pascal, it is recommended to include USE32 unit into USES clause of each unit. USE32 unit redefines built-in 16-bit integer types Integer and Word as 32-bit Longint type (see source code for the USE32 unit: \VP\SOURCE\RTL\USE32.PAS). If you really need to use 16-bit integers, use SmallInt and SmallWord types instead of Integer and Word, or use fully qualified identifiers: System.Integer and System.Word. 2.2 POINTER TYPES ~~~~~~~~~~~~~~~~~ Virtual Pascal uses 32-bit flat memory model. Pointers in Virtual Pascal have the same size (4 bytes) but denote 32-bit flat memory address rather than 16-bit segment (or selector) and 16-bit offset. As a result, Mem arrays have only one index - 32-bit flat memory offset. Segment part of the memory address is not available. 2.3 INTEGER EXPRESSIONS ~~~~~~~~~~~~~~~~~~~~~~~ In Borland Pascal all byte sized operands of the integer arithmetic operator are converted to Integer type. In Virtual Pascal all byte and word sized operands of the arithmetic operator are converted to Longint type. 2.4 STANDARD UNIT IMPLEMENTATION DIFFERENCES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are six standard units shipped: System, Dos, Crt, Strings, WinDos and WinCrt. Source code for System unit is not available. Parameters to standard procedures/functions and function return values that in Borland Pascal have Integer or Word type are extended to be Longint. Actually, they remain to be of the Integer and Word type, but USE32 unit is used to redefine the meaning of the Word and Integer. If you do not include USE32 unit into uses clause and try to recompile your 16-bit code, you will have no portability problems for value-parameters to the standard procedures and functions that have Word or Integer arguments. For variable parameters, you will get 'Type mismatch' error, because in Virtual Pascal they are 32-bit. 2.4.1 SYSTEM UNIT ~~~~~~~~~~~~~~~~~~ Ptr standard function has only one parameter: 32-bit flat memory offset. Segment parameter is not available. 2.4.2 DOS UNIT ~~~~~~~~~~~~~~~ The following DOS specific procedures are not implemented: procedure Intr(IntNo: Byte; var Regs: Registers); procedure MsDos(var Regs: Registers); procedure GetCBreak(var Break: Boolean); procedure SetCBreak(Break: Boolean); procedure GetIntVec(IntNo: Byte; var Vector: Pointer); procedure SetIntVec(IntNo: Byte; Vector: Pointer); procedure Keep(ExitCode: Word); Procedure SwapVectors remains for compatibility but do nothing. New procedure FindClose is added. procedure FindClose(var F: SearchRec); It ends the search, initiated by FindFirst and closes the search record. FindClose should be issued whenever search record is no longer needed. Unlike DOS, OS/2 does not keep search information in the user program space (in the SearchRec). OS/2 returns only handle that identifies this information, so it should be freed, otherwise OS/2 runs out of search handles and all calls to FindFirst later on will fail. 2.4.3 WINDOS UNIT ~~~~~~~~~~~~~~~~~ The following procedures are not implemented: procedure Intr(IntNo: Byte; var Regs: TRegisters); procedure MsDos(var Regs: TRegisters); procedure GetCBreak(var Break: Boolean); procedure SetCBreak(Break: Boolean); procedure GetIntVec(IntNo: Byte; var Vector: Pointer); procedure SetIntVec(IntNo: Byte; Vector: Pointer); New procedure FindClose is added. procedure FindClose(var F: TSearchRec); It has the same purpose as FindClose procedure of the Dos unit. 2.4.4 CRT UNIT ~~~~~~~~~~~~~~ The following procedures are not implemented: procedure Sound(Hz: Word); procedure NoSound; You can use new procedure PlaySound instead. Essentially, it is the equivalent to three calls: Sound(Freq); Delay(Duration); NoSound; procedure PlaySound(Freq,Duration: Longint); 2.4.5 WINCRT AND STRING UNIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All procedures and functions are implemented. 2.4.6 32-BIT TURBO VISION FOR OS/2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32-bit Turbo Vision for OS/2 is available as a patch on original Borland Pascal Turbo Vision sources. Run TV4VP OS/2 command file in the \VP\SOURCE\TV directory for the details of how to apply the patch. Low level Drivers and Objects units have been rewritten completely, in other units all assembler code has been rewritten. DOS specific TEmsStream object is not implemented. TEvent record is extended to include ShiftState byte field for evKeyDown variant. Critical error handlers are not available. OS/2 handles critical errors in a proper way (unlike DOS, OS/2 does not destroy user screen). FormatStr procedure is rewritten in built-in assembler. High level units such as Menus, Dialogs, etc, remains practically unchanged. 2.5 COMPILER DIRECTIVES ~~~~~~~~~~~~~~~~~~~~~~~ All Borland Pascal compiler directives that are implemented in Virtual Pascal have the same spelling. New switch directives introduced in the Virtual Pascal have names, consisting of several letters, unlike one letter switches of the Borland Pascal (surely, it is only 26 letters). Detailed description of the Virtual Pascal compiler directives can be found in the IDE help system. Several Borland Pascal directives are not available. Virtual Pascal simply ignores them. The alternative way of entering compiler directives is available. Comment that begins with, the ampersand (&) symbol, rather than dollar sign ($), is treated as a compiler directive. It is a convenient way to specify Virtual Pascal specific directives, Borland Pascal will treat them as ordinal comments. Borland Pascal 7.0 compiler directives that have no effect in Virtual Pascal: Switch compiler directives Switch³ Meaning ÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ $E ³ Emulation $F ³ Force FAR Calls $G ³ Generate 286 Instructions $K ³ Smart Callbacks $N ³ Numeric Coprocessor $O ³ Overlay Code Generation $W ³ Windows Stack Frame $Y ³ Symbol Reference Information Parameter directives Directive ³ Meaning ÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ $C Attribute ³Code Segment Attribute $D Text ³Description $G UnitName ³Group Unit Segments $O UnitName ³Overlay Unit Name $R FileName ³Resource File $S SegSize ³Segment Size Preference 2.6 BUILT-IN ASSEMBLER ~~~~~~~~~~~~~~~~~~~~~~ Built-in assembler is extended to support 386,486 and Pentium instructions. Two new operators are introduced: Small and Large. They are used to modify memory addressing mode (Small: 16-bit, Large: 32-bit). They have the same meaning and syntax, as in other 32-bit assemblers, such as MASM or TASM. There are two pseudo instructions available ALIGN and POPARGS. ALIGN pseudo instruction accepts one constant integer operand that can have the following values: 1: No code is generated. 2: Virtual Pascal generates code to align next instruction to the word (2-byte) boundary. 4: Virtual Pascal generates code to align next instruction to the double word boundary. Code, generated by the ALIGN instruction does not change any CPU register, except EIP. POPARGS pseudo instruction accepts one constant integer operand that defines the size of the arguments that should be popped out after current subprogram returns. It has meaning only for assembler procedures and functions. This value is used for RET instruction, generated by the END statement of the assembler procedure or function. In addition to @Params and @Locals symbols, @Uses symbol is introduced. It returns total size of the registers, saved in stack by the {$USES RegList} directive. 2.7 REGISTER USAGE ~~~~~~~~~~~~~~~~~~ Unlike Borland Pascal, Virtual Pascal have different register usage convention. By default, EBX, ESI and EDI registers are used as register variables to hold intermediate values across procedure or function calls and for register Self object pointer. If procedure or function uses these registers, they are saved on entry and restored on exit. Default register usage convention is compatible with SYSCALL calling convention used by OS/2 API functions. 32-bit C/C++ compilers have the same convention too. However, you can modify default register usage convention by $Saves parameter directive, but this is not recommended. 2.7.1 EMBEDDED ASM STATEMENTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ASM statements assume the default register convention or that one which is specified by the $Saves ($Alters) directive. For default register convention this means that EBX,ESI and EDI registers should not be changed. If you change one of them, you should inform compiler about this in the $Saves or $Alters directive. If ASM statement does not modify these registers and EAX,ECX or EDX, you may inform compiler either, so it can produce more efficient code. 2.7.2 ASSEMBLER PROCEDURES AND FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assembler procedures and functions should conform to the current register usage convention. $USES statement can help you with this. The $USES directive is like USES directive of the macro assemblers. It specifies registers that will be pushed at the beginning of the procedure or function and popped before return. You can also use $FRAME directive to specify whether to set up stack frame or not. For small assembler routines you can disable the generation of the stack frame ($FRAME- state). In this case, access to local variables and arguments is performed via ESP register. This generates the fastest code, but may produce bugs. Access to the local variable or argument is legal only if you does not change the value of the ESP register (there are no pushes or pops). 2.8 CODE GENERATION DIFFERENCES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Nested procedures and functions use different model for accessing local variables and arguments of the enclosing procedure or function. It is based on ENTER CPU instruction, which pushes stack frame pointers of all enclosing routines at the beginning of the nested procedure or function. See Intel documentation for the details. For overflow checking compiler uses INTO CPU instruction and for range checking - BOUND. This produces faster code when range and overflow checkings are enabled. 2.9 IMPORT AND EXPORT ~~~~~~~~~~~~~~~~~~~~~ Export and import are completely different. Virtual Pascal does not support EXPORTS clause, Name and Index standard procedural directives. Virtual Pascal offers more powerful and flexible language independent approach, see section 3 for the details. 2.10 Inline statements and inline subroutines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These Borland Pascal archaisms are not supported. Use ASM statement or assembler procedure/function instead. 3. NEW VIRTUAL PASCAL FEATURES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3.1 CALLING CONVENTIONS ~~~~~~~~~~~~~~~~~~~~~~~ Virtual Pascal supports Pascal, 16-bit Pascal (Far16) without thunking, C and StdCall calling conventions. Calling convention defines the order of the parameters and the way of stack clean up. You can change default calling convention by specifying compiler directive as follows: Directive ³ Convention ³ Parameter push order ³ Stack cleanup ÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ $Cdecl+ ³ C language ³ Last to first ³ Caller $Far16+ ³ 16-bit Pascal ³ First to last ³ Called routine $StdCall+³ STDCALL ³ Last to first ³ Called routine Disabled ³ 32-bit Pascal ³ First to last ³ Called routine These directives are mutually exclusive. If one directive is enabled, the other ones are disabled. Specifying any directive in the disabled state (-) enables default Pascal calling convention. For a procedure or function you can change the default calling convention by specifying Pascal, Cdecl, Far16 or StdCall standard procedure directive. Far16 Pascal calling convention is supported only for external procedures or functions. Compiler generates special code that calls external far 16-bit Pascal procedure or function via special helper routine. This helper routine has a restriction - you cannot specify more than 16 parameters to the Far16 procedure or function, if you try to specify more, compiler treats it as ordinal 32-bit Pascal. Virtual Pascal generates only 32-bit code, so Far16 directive is ignored, if it is used with non-external procedure or function. In this case calling convention would be 32-bit Pascal. It is worth to note, that you can create procedural types that use Pascal, Cdecl and StdCall calling conventions. Note, that unlike C/C++ compilers, calling convention of the Virtual Pascal does not change the case of the global identifiers and does not define whether to append leading underscore to global identifier or not. Next section describes naming convention used by Virtual Pascal. 3.2 NAMING CONVENTION ~~~~~~~~~~~~~~~~~~~~~ To satisfy the scope rules of Borland Pascal language, Virtual Pascal uses the following naming convention for public identifiers in the object file: UnitName@SymbolName UnitName@ObjectName@MethodName where UnitName is the name of the program, library or unit where symbol is defined. If program is written without heading (no program name is given), PROGRAM is assumed. SymbolName is the name of the variable, typed constant, procedure or function ObjectName is a name of the object type MethodName is a name of the object method. All names have their original case. However, for variables, typed constants, procedures and functions you can change default naming convention by specifying $OrgName+ directive. $OrgName+ puts original name of the symbol converted to upper case. Its primary purpose is to declare external OS/2 API functions, for example, see Os2Base unit source. You should also use it for interface variables, procedures and functions in your Pascal program or unit when you want to link it with modules written in other languages. 3.3 PURE INTERFACE UNITS ~~~~~~~~~~~~~~~~~~~~~~~~ Virtual Pascal stores symbol information about interface part of a unit in Virtual Pascal Interface file (.VPI). VPI files are compiler version dependent. Moreover, interface check sum sometimes depend upon compiler options used to compile unit. That is why, if you want to supply unit's object code without source, you should create pure interface unit for it. It should contain {$PureInt+} directive at the start of the unit and all interface part. If unit has an initialization part, it implementation part should be as follows: implementation begin end. otherwise only interface end. is needed. {PureInt+} directive forces the compiler to ignore undefined forward references to procedures, functions and methods, and assume that they are implemented in the original version of the unit. No object file or library is generated for pure interface unit, so when you compile it by any newer version of the compiler, it creates appropriate .VPI file for it and uses the object file or library produced from the original unit by the old version of the compiler. 3.4 DIRECT PORT ACCESS ~~~~~~~~~~~~~~~~~~~~~~ To obtain direct port access you should enable I/O privilege by specifying the following line in your OS/2 CONFIG.SYS: IOPL=YES If you use Port arrays in your Pascal program, you should either link it with DLL version of the run-time library or create linker module definition file for it with the following line included: SEGMENTS IO16 IOPL 3.5 IMPORT ~~~~~~~~~~ Virtual Pascal does not support Name and Index standard procedural directives of the Borland Pascal. External procedures or functions should be declared using only EXTERNAL standard directive, whether they are imported or not. It is totally transparent to the language. It is linker prerogative to know whether symbol is imported. Replacing static libraries by import libraries one can easily create applications that use either static or dynamic versions of the libraries. If procedure or function is imported, there are two ways to declare module name, entry name or ordinal number: - Use module definition file to specify this information. You should take into consideration naming convention of the Virtual Pascal (see 3.2 for details). - Create an import library for your dynamic link library. Then you can use its name in the $L parameter directive in a program or library which uses your DLL. Import library is created automatically by the IDE when you compile dynamic link library. It has the same name as a primary file of the library and has a .LIB extension. It is placed to the directory that is mentioned first in the Options³Directories³Library directories input box. Default import library OS2.LIB contains the import declarations of the OS/2 API functions. You need not specify it in the $L directive. 3.6 EXPORT ~~~~~~~~~~ Virtual Pascal does not support EXPORTS clause of the Borland Pascal. You can export procedure or function by specifying Export standard directive in its declaration. Note, that unlike Borland Pascal, it can be applied only to the procedure or function in the interface part of a unit, or any procedure or function in the program or library source file. As for the import, it is possible to use module definition file to export procedures, functions, variables and typed constants from the interface part of a unit or from the program or library source file. You can also export the whole interface part of the unit, including procedures, functions, object methods, variables and typed constants. You should only specify required unit name as a parameter to the $Export directive in the dynamic library source file, and that is all. See source file for DLL version of the Virtual Pascal run-time library for an example (\VP\SOURCE\RTL\VPRTL*.*). 3.7 PRESENTATION MANAGER RESOURCES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Virtual Pascal uses OS/2 resource compiler RC.EXE to compile resource script file and to bind binary resource file to the executable. Virtual Pascal IDE uses the following convention: resource script file (.RC) should be located in the directories specified in the Option³Directives³Resource directives input box or in the current directory, have the same name as primary file of the program or library, but have a .RC extension. If the IDE finds such a file, it looks for a binary resource file in the output directory (Options³Directories³Output directory input box) that has the same name but a .RES extension. If there is no binary resource file or it is older than resource script file, the IDE invokes RC to compile script file to binary resource file. Then RC is invoked to bind binary resource file to the application or dynamic link library executable. If your resource script file consists of several include files and you have modified one of them, you should 'touch' (update date) the primary script file, so the IDE may recognize that it is changed. 3.8 WRITING OS/2 DYNAMIC LINK LIBRARIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dynamic link libraries generally fall into two categories - subroutine libraries and subsystems. Virtual Pascal lets you create both types of the dynamic link libraries, but subroutine libraries are commonly used. Note, that source level debugging is not available for procedures and functions located in the library source file, so it usually contains only library heading, uses clause, and initialization part (usually for subsystems). 3.8.1 SUBROUTINE LIBRARIES ~~~~~~~~~~~~~~~~~~~~~~~~~~ Subroutine libraries are the most convenient way of creating dynamic version of the units. Procedures, functions and object methods in the subroutine library are written and execute in the same way as a statically linked ones. Units, included into dynamic link library works exactly as they were linked statically. The only difference is that actual linking occurs at load time instead of linking time. OS/2 creates unique static unit data (global variables and typed constants) for each application that uses subroutine dynamic link library. Subroutine libraries need not initialization and termination code. You must use module definition file to create dynamic link library. Typically it consists of three statements: LIBRARY LibName ; specifies DLL name DATA MULTIPLE NONSHARED ; forces OS/2 to create new ; instances of data segments for ; each application that uses DLL DESCRIPTION 'Text' ; Inserts specified text into ; the library executable file 3.8.2 SUBSYSTEMS ~~~~~~~~~~~~~~~~ The term subsystem refers to a DLL that provides a set of services built around a resource. The term resource is used in the most general sense of the word, do not confuse it with Presentation Manager resource. A subsystem usually has to manage a limited resource for an effectively unlimited number of clients. That is why, subsystems have common data segment for all applications (clients) that use it. To keep track of its clients, subsystem needs to know when new clients arrive and when old clients terminate. There are two forms of subsystem initialization and termination - global and instance. A subsystem can specify either service but not both. If global initialization is specified, the initialization entry point is called only once per activation of the subsystem. When the DLL is first referenced, OS/2 allocates the subsystem's static data segments, taking their initial values from the .DLL file. OS/2 then calls the subsystem's global initialization entry point so that the module can do its one-time initialization. The second form of initialization is instance initialization. The instance initialization entry point is called in the same way as the global initialization entry point except that it is called for every new client when that client first attaches to the DLL. The same applies to the DLL termination. You must use module definition file to create subsystem's dynamic link library. Typically it consists of three statements: LIBRARY LibName ; specifies DLL name DATA SINGLE NONSHARED ; only one data segment is created DESCRIPTION 'Text' ; Inserts specified text into ; the library executable file can be either INITGLOBAL or INITINSTANCE, can be either TERMGLOBAL or TERMINSTANCE. The initialization and termination entry points are the same. They correspond to the initialization statement part of a library. To check whether initialization or termination is underway, you should use assembler function like this: { Returns True for DLL initialization } function IsInit: Boolean; assembler; {$USES None} {$FRAME-} asm cmp [ebp+0Ch],0 sete al end; It checks special parameter passed to the DLL initialization / termination by OS/2. It is 0 for initialization and 1 for termination. The usual sybsystem initialization part is the following: begin if IsInit then begin ... Initialization stuff goes here end else begin ... Termination stuff are placed here end.