Re: Powerbasic & QuickBa

 BBS: Inland Empire Archive
Date: 04-24-92 (04:24)             Number: 154
From: LAWRENCE GORDON              Refer#: NONE
  To: DARYL POSNETT                 Recvd: YES 
Subj: Re: Powerbasic & QuickBa       Conf: (2) Quik_Bas
 On 04-19-92 Daryl Posnett wrote to Lawrence Gordon...

 DP> LG>PowerBasic can't use these libraries because of inherent
 DP> incompatibilities
 DP> LG>with the BC compiler; yet it has no trouble linking C and ASM .OBJ
 DP> LG>files, provided that compatible calling conventions and memory models
 DP> LG>are used.
 DP>
 DP> That's good to know, It is a real problem with QB. I have tried to do
 DP> fun stuff with QB and C, only to end up reaching for the big red switch.

Daryl - here's how to link in Turbo C routines with PowerBasic:

 1. Set Options/Compiler/Model to Huge.  <---necessary
 2. Set Options/Compiler/Defines, do nothing here

 3. Set Options/Compiler/Code Generation as follows:
   Calling convention       C
   Instruction set          8088/8086
   Floating Point           Emulation
   Default char type        Signed
   Alignment                Byte          <---necessary
   Generate underbars       OFF           <---necessary
   Merge duplicate strings  OFF
   Standard Stack Frame     ON
   Test stack overflow      OFF
   Line numbers             OFF
   Obj debug information    ON            <---not necessary

 4. Set Options/Compiler/Optimization
   Optimize for             Size
   Use register variables   On
   Register optimization    Off
   Jump optimization        Off

 5. Set Options/Compiler/Source
   Identifier length        32
   Nested comments          Off
   ANSI keywords            Off

 6. Set Options/Compiler/Names/Code Names/Segment name to CSEG.
    Set Options/Compiler/Names/Code Names/Group   name to
    Set Options/Compiler/Names/Code Names/Class   name to
    (yes, even remove the '*', it defaults to it->*.)

 7. Set Options/Compiler/Names/Data names/Segment name to DSEG.
    Set Options/Compiler/Names/Data Names/Group   name to
    Set Options/Compiler/Names/Data Names/Class   name to
    (yes, even remove the '*', it defaults to it-> *.)

 8. Set Options/Compiler/Names/BSS  Names/Segment name to
    Set Options/Compiler/Names/BSS  Names/Group   name to
    Set Options/Compiler/Names/BSS  Names/Class   name to
    (yes, even remove the '*', it defaults to it-> *.)
    (not necessary but recommended.)

 9. You DO NOT have to Options/Linker/Initialize segments).
      Map file               OFF      <---not necessary
      Initialize segments    ON
      Default libraries      OFF
      Graphics Library       ON       <---not necessary
      Warn duplicate symbols OFF
      Stack warning          ON
      Case-sensitive link    ON

 10. Set Options/Directories
     Set this as needed

 11. Set Options/Arguments
     this is not used

 12. After selection all your options be sure to save them.

 Now you can $LINK the .OBJ module into your PB program as usual.
     Source code is shown below.

Here's a simple example of a C function that takes an integer as a
parameter, adds 100 to it, and returns it to the PB program:

TC: PBINT.C

/* compile this to PBINT.OBJ  */
int pascal DOCALC (int far *pbvar)
{
  return (*pbvar)+100;
}

PB: INTEXAMP.BAS

$link "pbint.obj"
declare function DOCALC%(integer)
print DOCALC%(5)     'prints 105 (5+100)


Some things to note: the C function is declared to use PASCAL
calling conventions (the C function must clean up the stack
after the call, not PB, and because of the way C pushes
variables onto the stack); the parameter PBVAR is declared
to be a far pointer to an integer since PB passes all parameters
as far pointers; the function has a return type of INT
which causes the returned integer to be placed in the AX register
upon return (which is what PB expects of an external function
that returns an integer); and PB's DECLARE statement must explicitly
specify that the C function is an integer function that takes
an integer as a parameter.

Here's a simple example of a C routine that changes the
first character of a PB string passed to it as a parameter:

TC: PBSTRING.C

/* compile this to PBSTRING.OBJ */

#include <dos.h>

void pascal DOSTR(unsigned far *stseg, unsigned far *stofs, int far *stlen)
{
  char far *stdata;     /* will point to actual string data */

  if (*stlen) {         /* if string length > 0 */
    stdata = (char far *) MK_FP(*stseg, *stofs);  /* get data pointer */
    if (stdata)         /* if valid string */
      *stdata = 'J';    /* change 1st char of string to 'J' */
  }
}

PB: CSTRING.BAS



$link "pbstring.obj"
declare sub DOSTR(integer,integer,integer)

a$="Hello!"
call DOSTR(strseg(a$),strptr(a$),len(a$))   'pass segment/offset/length
print a$      'will print "Jello!"

Note: The C routine must not change the length of the string passed
to it.  Also, this example works for both regular and flex strings.

Larry.

... OFFLINE 1.36

--- Maximus 2.00
 * Origin: St. Louis User's Group BBS (1:100/4)
Outer Court
Echo Basic Postings

Books at Amazon:

Back to BASIC: The History, Corruption, and Future of the Language

Hackers: Heroes of the Computer Revolution (including Tiny BASIC)

Go to: The Story of the Math Majors, Bridge Players, Engineers, Chess Wizards, Scientists and Iconoclasts who were the Hero Programmers of the Software Revolution

The Advent of the Algorithm: The Idea that Rules the World

Moths in the Machine: The Power and Perils of Programming

Mastering Visual Basic .NET