Qbasicnews.com

Full Version: C++/QBasic
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3 4
I recently started learning C++, and I heard you could make libs from C++ to use in QBasic. This would be nice to speed up critical loops, etc. How do you do it? And remember that I'm an utter newb at c++.
Not in C++, but in C. C++ need too much libraries and runtimes which are not compatible with QB.

The best pick is getting an old 16 bits C compiler like Borland C 3.1 or Quick C 2.5. Quick C 2.5 and QuickBasic are said to work really well better. I am currently researching on the topic, so stay tuned. I can't help more.

Anyhow, in the ABC packets (http://www.allbasiccode.com) there was a small documents that introduced the topic, I think to remember. I'll dig for it, it has to be somewhere...

[EDIT]

Well, here it is:

Code:
'===========================================================================
' Subject: LINKING C TO BASIC                 Date: 07-15-97 (16:03)      
'  Author: Tika Carr                          Code: Text                  
'  Origin: t.carr@pobox.com                 Packet: FAQS.ABC
'===========================================================================
                ========================================
               [         QuickBasic 4.5 Tutorial        ]
               [ Interfacing QuickBasic with C Programs ]
               [    Copyright (c) 1997 by Tika Carr     ]
                ========================================
        (Please read disclaimer at the end of this tutorial.)

While QuickBasic is quite powerful for most applications, there are
times when a programmer would get more speed or efficiency when using a
C function, but would rather not write the whole program in C. In this
tutorial, I hope to cover some of the basics of interfacing C programs
with QuickBasic 4.5. This can't be done as easily with QBasic because
QBasic cannot use .OBJ files of compiled C programs. It MIGHT be done
somehow, but the methods are beyond the scope of this tutorial. If you
would like to use your QuickBasic .OBJ files in your C programs,
unfortunately this isn't possible. Reason is because the .OBJ files that
QuickBasic creates contains calls to QuickBasic functions, statements
and keywords (like PRINT, CLS and so on). The code for that is in the
run time library and therefore cannot be transferred in the .OBJ file
for use in a C compiler. However, you CAN use .OBJ files from some C
compilers and assemblers in QuickBasic. This tutorial will focus on
how to use C functions in QuickBasic.

INFORMING QUICKBASIC OF A C FUNCTION
====================================
Keep in mind that C doesn't really have any SUBroutines, only functions.
Subroutines can be written as 'void' functions which will behave as a
QuickBasic SUB (does not return a value).

To let QuickBasic know you want to use an external routine, you still
have to DECLARE it. For example, let's suppose we have a C function
called PrintIt and passing to it 3 variables:

void PrintIt(int x, int y, char *text)

Some knowledge of how C handles passing of parameters is necessary when
interfacing with QuickBasic. For variables that you are passing just the
value of (not a pointer, ie. the variable doesn't have an asterisk (*)
preceding it), you must let QuickBasic know its being passed by value by
using BYVAL. SEG is used for parameter variables that are pointers (as
in char *text above) SEGment, meaning pass the segment ADDRESS of the
variable, not the value). Here's an example using our above PrintIt
function:

DECLARE SUB PrintIt(BYVAL x AS INTEGER, BYVAL y AS INTEGER,_
SEG text AS STRING)

(Note that the underscore _ is used to indicate that the second line is
really part of the first, and should be joined there. Just wasn't enough
room on a line to fit it all in.)

This example won't work yet but we'll get to why in a moment. This
example just shows how to pass the parameter's value or address. It is
also important to be sure and state what type of variable is used:

  If declared in C as        use this in QuickBasic
-----------------------------------------------------
       int                     AS INTEGER
       char                    AS STRING
         (note that QB doesn't accept AS STRING * n in a DECLARE)
       double                  AS DOUBLE
       float                   AS SINGLE
       long                    AS LONG

In the case of a C function that passes a value:

int PrintIt(int x, int y, char *text)

You would use:

DECLARE FUNCTION PrintIt% (BYVAL x AS INTEGER, BYVAL y AS INTEGER,_
SEG text AS STRING)

Here note the % after PrintIt. This tells you its an INTeger. See the
QuickBasic online help and Manual for the symbols for different variable
types and match them accordingly. A type of 'void' is to be declared as
a SUB and not a function.

Now that we know how to declare the parameters, we have to be sure they
are in the right order. When QuickBasic sees a function written in
C, it reads the parameters in _backwards_. For instance, taking our
example:

void PrintIt(int x, int y, char *text)

QuickBasic looks at it like this:

SUB PrintIt(text$, y%, x%)

There are two ways to get QuickBasic to see the parameters in the right
order. If you wrote the C program yourself, you can use the pascal or,
on some compilers, _pascal keyword to tell the C Compiler that the
parameters are to be passed in Pascal order (which is the same way
QuickBasic uses). Here's how we'd rewrite the above C function:

void pascal PrintIt(int x, int y, char *text)

Some C compilers (namely Borland and some others) also let you set all
the parameters to be passed using Pascal order by a setting in the
compiler's IDE configuration. This can cause some problems, though, if
you have other functions in the C source that are going to also use the
same function that is to be used in QuickBasic. When doing this type of
programming, you will have to be sure when you use pascal only on the
functions that are not used by other ones in the C source, or else leave
it off and declare it as CDECL in the QuickBasic program (discussed in a
moment). There are other ways around this too, which is beyond the scope
of this tutorial. Most C programmers would know of these other options.

When you compile the function in C that you used the pascal keyword in,
it will be all set so that QuickBasic can read it. Then just declare it
in QuickBasic as:

DECLARE SUB PrintIt(BYVAL x AS INTEGER, BYVAL y AS INTEGER,_
SEG text AS STRING)

However, there are times when you are told an .OBJ file was compiled in
C but you may not have the actual source code to it, and therefore can't
make any changes. So, do we just declare the parameters in backwards
order? Well, not quite. QuickBasic has CDECL which will let you tell it
that you are using a C function:

C function:  void PrintIt(int x, int y, char *text)

QuickBasic Declaration:

  DECLARE SUB PrintIt CDECL (BYVAL x AS INTEGER, BYVAL y AS INTEGER,_
  SEG text AS STRING)

This lets QuickBasic know that the parameters are actually being passed
in reverse order, or CDECLare (C-DECLARE).

COMPILING AND LINKING IN THE C FUNCTION
========================================
If you are writing the C function yourself, you may want to be double
sure that you don't have it compile in any debug information. Some
compilers have IDEs that are set to add in debug info so that you can
step through your C program, much like the Debug in QuickBasic does. To
be best compatible with QuickBasic, you will want this turned off. Also
be sure your compiler will create Microsoft-compatible .OBJ files.
Microsoft products like Quick C will do this but some other compilers
may also be Microsoft compatible. Sometimes you may need to compile the
program using the assembler that comes with the compiler, and not the
compiler itself (as sometimes may be the case with Borland C++ 3.1, for
example). You'll need to be familiar with your compiler and its IDE
and/or other configurations (if any) to get the best results. If nothing
works, then its probably because the .OBJ files are just not compatible.

After you created (or obtained) an .OBJ file of the C function, you will
need to link them into your program. First be sure that LINK.EXE and
LIB.EXE are in your PATH or current directory where the .OBJ files are
and also the BQLB45.LIB, and possibly the QB.LIB (if you plan to use
INTERRUPTs in your program too).

I normally make the QLB file first:

LINK /Q CPROG1.OBJ CPROG2.OBJ CPROG2.OBJ, CPROG.QLB,,BQLB45.LIB;

This creates the CPROG.QLB file and a .MAP file that you can delete (but
sometimes may be helpful to look at in case of problems).

If you are going to use interrupts, change the BQLB45.LIB; above to:
BQLB45.LIB+QB.LIB;

Next make the Library so that you can also compile your program:

LIB CPROG.LIB+CPROG1.OBJ+CPROG2.OBJ+CPROG3.OBJ;

Or, if planning to use interrupts too:

LIB CPROG.LIB+CPROG1.OBJ+CPROG2.OBJ+CPROG3.OBJ+QB.LIB;

This makes your CPROG.LIB file. Now just start QB with: QB /L CPROG.QLB
and make the declarations as explained earlier in this tutorial. Its
best to create this as a .BI file and '$INCLUDE: 'CPROG.BI' for example,
in your program. You can also use more than one $INCLUDE in your
program. This is useful if you need to also use QB.BI for INTERRUPTs.

PROBLEMS IN LINKING THE OBJ FILE TO A QLB
-----------------------------------------
L1101  invalid object module

This is probably one of the more common ones, and most of the time is
because your OBJ file is not compatible somehow with QuickBasic.
Normally, it may be because you inadvertently included some of the C
compiler's Debug information (as explained previously). If this don't
help, try compiling using the assembler or compiling to assembly source
and using a Microsoft compatible assembler to compile the .OBJ file, if
possible. There are times though when there doesn't seem to be a fix.
Those are the ones that just aren't compatible. Best try another C
compiler and/or assembler if that happens.

L2029 unresolved externals

This is another common problem when linking. This occurs for basically
the same reason as the L1101 error above does, but may also be something
in your C program. Does anything in your C program call any external
functions that are not included in the compiling? Perhaps from another
program or source? You will have to compile that source too and include
the OBJ file in.

Another common problem is you may find "printf" or other standard
library functions to be one of the unresolved externals. This means that
the .OBJ file is made so that the C Compiler knows where and what printf
is. But, QuickBasic does not. One solution you may want to try if your
compiler supports it, is to compile to an assembly language source, then
compile that to an .OBJ file with an assembler. Basically, you want to
be sure that the .OBJ is pure machine language, and nothing external
being called that isn't going to be included in your QuickBasic library.

L2041 stack plus data exceed 64K

This sometimes occurs if you compiled the program using an incompatible
memory model. For best results, use the medium, compact or small memory
model to compile C functions that will be used in QuickBasic.

These are the most common ones you might run into. For other linker
errors (and more detailed descriptions of these) see your QuickBasic
manual, section 2, pp. 420 - 431.

ERRORS IN RUNNING THE QUICKBASIC PROGRAM
----------------------------------------
One of the most common ones is that QuickBasic will say that the sub or
function is not found in the Quick Library. In that case, be sure you
loaded the Quick Library. You may also want to double check all your
steps and try compiling and linking again. If you used an assembler to
compile the source, perhaps the assembler did not specify the function
as '.public'. You may have to use a text editor to make that change in
the assembly source code and re-assemble it.

Another common error is that QuickBasic may find something wrong with
the list of parameters. Be sure you have it declared right, and are sure
of the way the parameters are seen in QuickBasic. Maybe you didn't use
CDECL in QuickBasic or pascal in your C function. You can't do both. You
can only use CDECL in QuickBasic's DECLARE =OR= use the pascal keyword
in the C function. Doing both puts us in the same position of one seeing
the list of parameters in reverse order than what was intended.

                    ******* DISCLAIMER *******

The author of this article cannot guarantee the usability or
suitability of the information presented herein for any particular
purpose. In addition, the user of the information in this article
agrees not to hold the author, moderator or any other direct or
indirect agent liable in any way for any damages, loss of data, or
other consequences arising from use of this information. If laws in your
area do not allow this type of disclaimer than DON'T USE THIS
INFORMATION! While I have made every conscious effort to ensure the
information in this tutorial is accurate, the end result depends on
the person making use of the information presented here. Use the
information in this tutorial at your own risk.

                  ******* CONTACT INFORMATION *******

As of 7/11/1997, comments, questions and suggestions, can be directed
to:

FidoNet: Tika Carr 1:2613/601 or 1:2613/313
Internet: t.carr@pobox.com

=====================================================================
All compilers and products mentioned are copyright and/or trademarks of
their respective owners.
Yeah, but now we need Microft or Quick C... Sad
That's not a problem ^_^

http://imaginatica.us.es/~wopr2k/compilers/qc25.zip

Warning! 3.4 Megs, complete package (includes tutorials).

(if it doesn't work NOW try in 10 minutes, I am uploading it in this moment) Enjoy
Thanks! This should help a lot. 8)
Oooh...*clicks*...
I assume this is QuickC? Excellent...yet another addition to my C directory... Big Grin
As long as I've made this topic.... Does anyone have any good C++ books they'd recommend? There's like a billion or so out there, so I'd like to know if there are any especially good ones.
I've learned all my C so far from Learn C in 21 Days - it's full of typos, though.
Best bet: get a college textbook. They're always amazing.
Wait, so does QB not handle the call stack like other languages?
Why do you say that? I believe QB uses the stack for functions the normal way.
Pages: 1 2 3 4