Using a freebasic dll in c++

New to FreeBASIC? Post your questions here.
dodicat
Posts: 7979
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Using a freebasic dll in c++

Post by dodicat »

Hi basiccoder2
I have found a way to load dll's into c++ via code (no need to alter anything in the dev c++ ide settings)

From scratch
Put this .bas file and the c++ file in the same folder.

graphics.bas
compile with -dll to get graphics.dll

Code: Select all

'graphics.bas --- a dll for C++ or FreeBASIC
'compile with -dll
extern  "C++"
Sub screen1 (Byval X As Integer, Byval Y As Integer,xres as integer,yres as integer,b as integer) EXPORT
  Screenres xres,yres,b
  SCREENCONTROL(100, X, Y)
End Sub

sub clearcolor(c as uinteger) export
    color ,c
    cls
    end sub

function rgbcolor(r as integer,g as integer,b as integer) as uinteger export
    return rgb(r,g,b)
end function

Sub drawstring (x as integer,y as integer, text As zstring ptr,c as uinteger) EXPORT
 draw string (x,y),*text,c
End Sub

sub printdbl(n as double,flag as integer=0) export
    select case as const flag
    case 0:print n
    case 1:print n,
    case 2:print n;
    case else
        print n
        end select
    end sub

sub line1(x1 as integer,y1 as integer,x2 as integer,y2 as integer,c as uinteger) EXPORT
    line (x1,y1)-(x2,y2),c
end sub

sub sleep1(t as integer) export
    sleep t 
end sub

sub waitkey export
    sleep
end sub

function randoms(n as integer) as double export
    return rnd*n
    end function

sub circlefill1(x1 as integer,_
    y1 as integer,_
    rad as integer,_
    c as uinteger) export
    circle (x1,y1),rad,c,,,,f
end sub

sub circle1(x1 as integer,_
    y1 as integer,_
    rad as integer,_
    c as uinteger) export
    circle (x1,y1),rad,c
end sub

sub pset1(x1 as integer,y1 as integer,c as uinteger) EXPORT
    pset (x1,y1),c
end sub

sub clearscreen1() export
    cls
end sub

sub endkey1(n as integer) export
    if inkey=chr(n) then end
end sub

sub screenlock1(dummy as integer) export
    screenlock
end sub

sub screenunlock1(dummy as integer) export
    screenunlock
end sub

sub getmouse1( mx as integer ptr, my as integer ptr, mw as integer ptr, mb as integer ptr) export
    getmouse(*mx,*my,*mw,*mb)
end sub
sub locate1(x as integer,y as integer) export
    locate x,y
end sub

Function framecounter() As Integer export
    dim as double t2=timer
    Static As Double t3,frames,answer
    frames=frames+1
    If (t2-t3)>=1 Then
        t3=t2
        answer=frames
        frames=0
    End If
    Return answer
End Function

Function regulate( MyFps As integer, fps As integer ptr) As integer export
    Static As Double timervalue,lastsleeptime,t3,frames
    frames+=1
    If (Timer-t3)>=1 Then t3=Timer:*fps=frames:frames=0
    Var sleeptime=lastsleeptime+((1/myfps)-Timer+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    lastsleeptime=sleeptime
    timervalue=Timer
    Return sleeptime
End Function

end extern
 
and the c++ file

Code: Select all



#include <windows.h>
#include <math.h>
#include<new>
 
 typedef double ( * thernd)(int);
 typedef void (* thescreen)(int,int,int,int,int);
 typedef void  (* thedrawstring)(int x,int y,char* text,unsigned int c);
 typedef void ( * theprintdbl)(double n,int flag);
 typedef void ( * thecirclefill1)(int x1,int y1,int rad,unsigned int c);
 typedef void ( * thecircle1)(int x1,int y1,int rad,unsigned int c);
 typedef void ( * theline1)(int x1,int y1,int x2,int y2,unsigned int c);
 typedef unsigned int ( * thergbcolor)(int r,int g,int b);
 typedef void ( * thescreenlock1)();
 typedef void ( * thescreenunlock1)();
 typedef void ( * thesleep1)(int n);
 typedef void ( * theclearscreen1)();
 typedef void ( * theendkey1)(int);
 typedef void ( * thelocate1)(int x,int y);
 typedef int ( * theframecounter)();
 typedef void ( * thegetmouse1)(int *mx,int *my,int *mw,int *mb);
 typedef int ( * theregulate)(int myfps,int *fps);
 typedef void ( * theclearcolor)(unsigned int c);
 typedef void ( * thepset1)(int,int,unsigned int);
 typedef void ( * thewaitkey)();
 
 HMODULE Module = LoadLibrary("graphics.dll");
 
 
     thernd  rnd = (thernd) GetProcAddress(Module, "_Z7randomsi");
     thescreen  screen = (thescreen) GetProcAddress(Module, "_Z7screen1iiiii");
     thedrawstring  drawstring = (thedrawstring) GetProcAddress(Module, "_Z10drawstringiiPcj");
     thergbcolor   rgb= (thergbcolor) GetProcAddress(Module, "_Z8rgbcoloriii");
     theprintdbl  print=  (theprintdbl) GetProcAddress(Module, "_Z8printdbldi");
     thecirclefill1 circlefill= (thecirclefill1) GetProcAddress(Module, "_Z11circlefill1iiij");
     thecircle1 circle = (thecircle1)  GetProcAddress(Module, "_Z7circle1iiij");
     theline1 line =(theline1) GetProcAddress(Module, "_Z5line1iiiij");
     thescreenlock1 screenlock=(thescreenlock1) GetProcAddress(Module, "_Z11screenlock1i");
      thescreenunlock1 screenunlock = ( thescreenunlock1) GetProcAddress(Module, "_Z13screenunlock1i");
      thesleep1 sleep = (thesleep1) GetProcAddress(Module, "_Z6sleep1i");
      theclearscreen1  clearscreen = (theclearscreen1)GetProcAddress(Module, "_Z12clearscreen1v");
      theendkey1 endkey = (theendkey1) GetProcAddress(Module, "_Z7endkey1i");
      thelocate1 locate = (thelocate1) GetProcAddress(Module, "_Z7locate1ii");
      theframecounter framerate = (theframecounter) GetProcAddress(Module, "_Z12framecounterv");
       thegetmouse1 getmouse = ( thegetmouse1)  GetProcAddress(Module, "_Z9getmouse1PiS_S_S_");
       theregulate regulate = (theregulate)  GetProcAddress(Module, "_Z8regulateiPi");
       theclearcolor clearcolor = (theclearcolor) GetProcAddress(Module, "_Z10clearcolorj");
       thepset1 putpixel = (thepset1) GetProcAddress(Module, "_Z5pset1iij");
       thewaitkey wait = (thewaitkey) GetProcAddress(Module, "_Z7waitkeyv");

  struct ball
{
	float x;
	float y;
	float dx;
	float dy;
	unsigned int col;
} ;

// globals
struct ball* b[3]={new ball,new ball,new ball};
 int fps,sleeptime;
 int mx,my,mw,mb;


// procedures
void move(struct ball* b[])
{
		for (int n=0;n<3;n++)
		{
b[n]->x+=b[n]->dx;
b[n]->y+=b[n]->dy;
}
}

void edges(struct ball* b[])
{
	int r=50;
	for (int n=0;n<3;n++)
	{

	if(b[n]->x<r) {
 		b[n]->dx=-b[n]->dx;
	 };
	 if(b[n]->x>1000-r){
 		b[n]->dx=-b[n]->dx;
	 };
	 if(b[n]->y<r){
 		b[n]->dy=-b[n]->dy;
	 };
	 if(b[n]->y>768-r){
 		b[n]->dy=-b[n]->dy;
	 };	
}

}

void draw(struct ball* b[])
{
	for (int n=0;n<3;n++)
	{	
circlefill(b[n]->x,b[n]->y,50,b[n]->col);
circle(b[n]->x,b[n]->y,50,rgb(255,255,255));

}
}


void BallCollisions(struct ball* b[])
{
float L,impulsex,impulsey,dot,impactx,impacty;           
            for(int n1=0;n1<3;n1++)
                {
                for(int n2=n1+1;n2<3;n2++)
                    {
            L=sqrt( (b[n1]->x-b[n2]->x)*(b[n1]->x-b[n2]->x) + (b[n1]->y-b[n2]->y)*(b[n1]->y-b[n2]->y));
          
            if (L<100)     // Then
                {
                 impulsex=(b[n1]->x-b[n2]->x)/L;
                 impulsey=(b[n1]->y-b[n2]->y)/L;
                //In case of overlap circles, reset to non overlap positions
                b[n1]->x=b[n2]->x+100*impulsex;
                b[n1]->y=b[n2]->y+100*impulsey;
                 impactx=b[n1]->dx-b[n2]->dx;
                 impacty=b[n1]->dy-b[n2]->dy;
                 dot=impactx*impulsex+impacty*impulsey;
                b[n1]->dx-=dot*impulsex;
                b[n1]->dy-=dot*impulsey;
                b[n2]->dx+=dot*impulsex;
                b[n2]->dy+=dot*impulsey;
                }
            }
        }
    
    }

 int main(void)
//set up balls
 {
 	b[0]->x=100;
 	b[0]->y=100;
 	b[0]->dx=5.2;
 	b[0]->dy=3.2;
 	b[0]->col=rgb(0,100,200);
 	
 	b[1]->x=600;
 	b[1]->y=200;
 	b[1]->dx=-5.2;
 	b[1]->dy=3.2;
 	b[1]->col=rgb(200,100,0);
 	
 	
 	b[2]->x=700;
 	b[2]->y=500;
 	b[2]->dx=-1.2;
 	b[2]->dy=3.2;
 	b[2]->col=rgb(0,200,0);
 	
 screen(50,20,1000,768,32);
 clearcolor(rgb(0,0,100));
 while (1)
 {
 
 	move(&b[0]);
 	edges(&b[0]);
 	BallCollisions(&b[0]);
	 
    screenlock();
 clearscreen();
 draw(&b[0]);
 
 
 drawstring(50,10," Press escape key to end",rgb (255,200,0));
 drawstring(0,55,"framerate",rgb(0,200,0));
 locate (8,11);
 print(fps,0);
 
screenunlock();
sleeptime=regulate(65,&fps);
sleep(sleeptime);
endkey(27);
}

 //delete [] b;
}
      
          
  
Note: you don't need the .dll.a file, you can delete it if you want.
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Using a freebasic dll in c++

Post by BasicCoder2 »

@dodicat,
Ok that is neat.
It worked! Three balls bouncing around the window and off each other.

It did however generate a warning.
||=== Build: Debug in fbTest (compiler: GNU GCC Compiler) ===|
C:\CPP_PROGRAMS\fbTest\main.cpp||In function 'int main()':|
C:\CPP_PROGRAMS\fbTest\main.cpp|175|warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]|
C:\CPP_PROGRAMS\fbTest\main.cpp|176|warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]|
||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 2 second(s)) ===|
||=== Run: Debug in fbTest (compiler: GNU GCC Compiler) ===|

I will have to spend some time studying your example.

Thanks for sharing.
Last edited by BasicCoder2 on May 08, 2018 1:21, edited 1 time in total.
dodicat
Posts: 7979
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Using a freebasic dll in c++

Post by dodicat »

If you have
drawstring(50,10,strdup(" Press escape key to end"),rgb (255,200,0));
drawstring(0,55,strdup("framerate"),rgb(0,200,0));
instead of the drawstrings already there, the warnings are gone.

I adjusted the balls for C only.
Actually C is more awkward than C++
The graphics can only be started and the procedures found from main (via a sub) .
So here is code for C (tested gcc), and it also compiles with C++ (tested)

Code: Select all

 


#include <windows.h>
#include <stdio.h>

typedef double ( * thernd)(int);
typedef void (* thescreen)(int,int,int,int,int);
typedef void  (* thedrawstring)(int x,int y,char* text,unsigned int c);
typedef void ( * theprintdbl)(double n,int flag);
typedef void ( * thecirclefill1)(int x1,int y1,int rad,unsigned int c);
typedef void ( * thecircle1)(int x1,int y1,int rad,unsigned int c);
typedef void ( * theline1)(int x1,int y1,int x2,int y2,unsigned int c);
typedef unsigned int ( * thergbcolor)(int r,int g,int b);
typedef void ( * thescreenlock1)();
typedef void ( * thescreenunlock1)();
typedef void ( * thesleep1)(int n);
typedef void ( * theclearscreen1)();
typedef void ( * theendkey1)(int);
typedef void ( * thelocate1)(int x,int y);
typedef int ( * theframecounter)();
typedef void ( * thegetmouse1)(int *mx,int *my,int *mw,int *mb);
typedef int ( * theregulate)(int myfps,int *fps);
typedef void ( * theclearcolor)(unsigned int c);
typedef void ( * thepset1)(int,int,unsigned int);
typedef void ( * thewaitkey)();
thecirclefill1 circlefill;
thernd  rnd;
thescreen  screen;
thedrawstring  drawstring;
thergbcolor   rgb;
theprintdbl  print;
thecircle1 circle;
theline1 line;
thescreenlock1 screenlock;
thescreenunlock1 screenunlock;
thesleep1 sleep;
theclearscreen1  clearscreen;
theendkey1 endkey;
thelocate1 locate;
theframecounter framerate;
thegetmouse1 getmouse;
theregulate regulate;
theclearcolor clearcolor;
thepset1 putpixel;
thewaitkey wait;

HINSTANCE dllmodule ;

void initgraphics()
{
dllmodule = LoadLibrary(TEXT("graphics.dll"));
if (dllmodule==0)
{
printf("Dll not found\n");
system("pause");
exit(EXIT_SUCCESS);
}

rnd = (thernd) GetProcAddress(dllmodule, "_Z7randomsi");
screen = (thescreen) GetProcAddress(dllmodule, "_Z7screen1iiiii");
drawstring = (thedrawstring) GetProcAddress(dllmodule, "_Z10drawstringiiPcj");
rgb= (thergbcolor) GetProcAddress(dllmodule, "_Z8rgbcoloriii");
print=  (theprintdbl) GetProcAddress(dllmodule, "_Z8printdbldi");
circlefill= (thecirclefill1) GetProcAddress(dllmodule, "_Z11circlefill1iiij");
circle = (thecircle1)  GetProcAddress(dllmodule, "_Z7circle1iiij");
line =(theline1) GetProcAddress(dllmodule, "_Z5line1iiiij");
screenlock=(thescreenlock1) GetProcAddress(dllmodule, "_Z11screenlock1i");
screenunlock = ( thescreenunlock1) GetProcAddress(dllmodule, "_Z13screenunlock1i");
sleep = (thesleep1) GetProcAddress(dllmodule, "_Z6sleep1i");
clearscreen = (theclearscreen1)GetProcAddress(dllmodule, "_Z12clearscreen1v");
endkey = (theendkey1) GetProcAddress(dllmodule, "_Z7endkey1i");
locate = (thelocate1) GetProcAddress(dllmodule, "_Z7locate1ii");
framerate = (theframecounter) GetProcAddress(dllmodule, "_Z12framecounterv");
getmouse = ( thegetmouse1)  GetProcAddress(dllmodule, "_Z9getmouse1PiS_S_S_");
regulate = (theregulate)  GetProcAddress(dllmodule, "_Z8regulateiPi");
clearcolor = (theclearcolor) GetProcAddress(dllmodule, "_Z10clearcolorj");
putpixel = (thepset1) GetProcAddress(dllmodule, "_Z5pset1iij");
wait = (thewaitkey) GetProcAddress(dllmodule, "_Z7waitkeyv");

}
// ===============================  end of library ===================( this bit could be called fbgraphics.h) ======
// then #include "fbgraphics.h"
// must use initgraphics(); inside main() C or C++

// start program

#include <math.h>



struct ball
{
float x;
float y;
float dx;
float dy;
unsigned int col;
} ;

// globals

struct ball b[3];
int fps,sleeptime;
int mx,my,mw,mb;


// procedures
void move(struct ball b[])
{
int n;
for (n=0;n<3;n++)
    {
    b[n].x+=b[n].dx;
    b[n].y+=b[n].dy;
    }
    }
    
    void edges(struct ball b[])
    {
   int r=50;
   int n;
   for ( n=0;n<3;n++)
        {
        
        if(b[n].x<r) {
       b[n].dx=-b[n].dx;
        };
        if(b[n].x>1000-r){
       b[n].dx=-b[n].dx;
        };
        if(b[n].y<r){
       b[n].dy=-b[n].dy;
        };
        if(b[n].y>768-r){
       b[n].dy=-b[n].dy;
        };   
        }
        
        }
        
        void draw(struct ball b[])
        {
        int n;
        for (n=0;n<3;n++)
            {   
            circlefill(b[n].x,b[n].y,50,b[n].col);
            circle(b[n].x,b[n].y,50,rgb(255,255,255));
            
            }
            }
            
            
            void BallCollisions(struct ball b[])
            {
            float L,impulsex,impulsey,dot,impactx,impacty; 
            int n1,n2;          
            for(n1=0;n1<3;n1++)
                {
                for(n2=n1+1;n2<3;n2++)
                    {
                    L=sqrt( (b[n1].x-b[n2].x)*(b[n1].x-b[n2].x) + (b[n1].y-b[n2].y)*(b[n1].y-b[n2].y));
                    
                    if (L<100)     // Then
                        {
                        impulsex=(b[n1].x-b[n2].x)/L;
                        impulsey=(b[n1].y-b[n2].y)/L;
                        //In case of overlap circles, reset to non overlap positions
                        b[n1].x=b[n2].x+100*impulsex;
                        b[n1].y=b[n2].y+100*impulsey;
                        impactx=b[n1].dx-b[n2].dx;
                        impacty=b[n1].dy-b[n2].dy;
                        dot=impactx*impulsex+impacty*impulsey;
                        b[n1].dx-=dot*impulsex;
                        b[n1].dy-=dot*impulsey;
                        b[n2].dx+=dot*impulsex;
                        b[n2].dy+=dot*impulsey;
                        }
                        }
                        }
                        
                        }
                        
                        int main(void)
                        {
                        
                        initgraphics();  //must do
                        
                        //set up balls
                        
                        b[0].x=100;
                        b[0].y=100;
                        b[0].dx=5.2;
                        b[0].dy=3.2;
                        b[0].col=rgb(0,100,200);
                        
                        b[1].x=600;
                        b[1].y=200;
                        b[1].dx=-5.2;
                        b[1].dy=3.2;
                        b[1].col=rgb(200,100,0);
                        
                        
                        b[2].x=700;
                        b[2].y=500;
                        b[2].dx=-1.2;
                        b[2].dy=3.2;
                        b[2].col=rgb(0,200,0);
                        
                        screen(50,20,1000,768,32);
                        clearcolor(rgb(0,0,100));
                        
                        while (1)
                            {
                            
                            move(&b[0]);
                            edges(&b[0]);
                            BallCollisions(&b[0]);
                            
                            screenlock();
                            clearscreen();
                            draw(&b[0]);
                            
                            
                            drawstring(50,10,strdup(" Press escape key to end"),rgb (255,200,0));
                            drawstring(0,55,strdup("framerate"),rgb(0,200,0));
                            locate (8,11);
                            print(fps,0);
                            
                            screenunlock();
                            sleeptime=regulate(65,&fps);
                            sleep(sleeptime);
                            endkey(27);
                            }
                            
                            
                            }
                            
                            
                                                  
 
    
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Using a freebasic dll in c++

Post by sancho3 »

@Dodicat:
I tried your code in Visual Studio using an empty project.
I thought it was freezing. It created an exe file but it wasn't running.
So I went to the command prompt and the exe ran fine (bouncing balls).
Finally I noticed Visual Studio was taking a long time loading other libraries like ole32.
Your code works fine in that IDE as well.

I know very little about c++ and using it in Visual Studio.
I wonder does anyone know any way to speed up building the project?
It takes about a minute to build this small project.
dodicat
Posts: 7979
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Using a freebasic dll in c++

Post by dodicat »

Thanks for testing sancho3
I use dev c++ or straight gcc from mingw.

Just a simple compile from a .cpp or .c (or .bas) to .exe or .o is all I need with a bare bones ide.
I realise that visual studio supports a few dozen languages, so I imagine it would be inherently bloated and difficult to navigate to the actual c++ compiler.
Is the compiler CL.exe?
https://msdn.microsoft.com/en-us/library/610ecb4h.aspx
Is it on your system path?
If it is then a straight compile should be possible.
I usually make a start shell in FreeBASIC:

Code: Select all

  shell "cmd"
I call it shell.exe and pop it into my working folder.
Then perhaps something like CL.exe myfile.cpp to see what happens.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Using a freebasic dll in c++

Post by sancho3 »

I will investigate further.
The biggest reasons I use VS is the debugger is the best I have seen.
I suppose I could use a command line compiler and just insert code to be debugged into VS as necessary.
I have the feeling that much of the slowness stems from settings that I don't understand.
Post Reply