Developing DLLs with FBC?
-
- Posts: 65
- Joined: Jul 01, 2021 7:53
Developing DLLs with FBC?
I wanted to be sure if the DLLs could be used with plain C but I think it's not the case. I guess it maybe if I don't use any OOP at all. From what I read FBC used the same name mangling rule as C++ so I think I could use this DLL with C++, isn't it? It's decorated the same way after all.
By using I mean writiing a C header (translated from FBC's .bi header), include this header in your plain C code then link with the DLLs. Of course one can always dynamic load this DLL but it's not what I'm asking about. Thanks.
By using I mean writiing a C header (translated from FBC's .bi header), include this header in your plain C code then link with the DLLs. Of course one can always dynamic load this DLL but it's not what I'm asking about. Thanks.
Re: Developing DLLs with FBC?
https://www.freebasic.net/wiki/ProPgSharedLibraries
Yes a shared library compiled with fbc can be linked to by a C or C++ program. You're incorrect about the name mangling issue. FB only mangles names in a way compatible with C++ if you use the extern "c++" block. Normally FB mangles the names in a way that only FB understands. But if you export the symbol, then FB does not mangle it at all.
Yes a shared library compiled with fbc can be linked to by a C or C++ program. You're incorrect about the name mangling issue. FB only mangles names in a way compatible with C++ if you use the extern "c++" block. Normally FB mangles the names in a way that only FB understands. But if you export the symbol, then FB does not mangle it at all.
-
- Posts: 65
- Joined: Jul 01, 2021 7:53
Re: Developing DLLs with FBC?
It's not about linked or not my friend. I mean something very different.caseih wrote:https://www.freebasic.net/wiki/ProPgSharedLibraries
Yes a shared library compiled with fbc can be linked to by a C or C++ program. You're incorrect about the name mangling issue. FB only mangles names in a way compatible with C++ if you use the extern "c++" block. Normally FB mangles the names in a way that only FB understands. But if you export the symbol, then FB does not mangle it at all.
For example, I developed the DLL with OOP on FB. To be able to use this DLL on C++, do I just use it as is (call FB object the same way as C++ object since they are `compatible`, I think?), or I had to flattern it (the same way C user has to flattern C++ OOP into simple C constructs: class into struct, methods into functions,...)? If I don't use any OOP features on FB, could I use this DLL with C easily by just translating the .bi header into .h header? This is what I wanted to know.
Re: Developing DLLs with FBC?
I had some problems using a dll from fb to c++.
I suppose a worthwhile dll to use in c++ is the fb graphics (gfx).
Here I show only three functions from a dll I created in fb, all the functions were tagged export.
I put this dll (graphics.dll) into the same folder as my c++ code.
Here is how I got them in c++.
I had to use the decorated names (I got them from the .def file via gendef).
This was a while back, but I fluffed around to try and use non decorated names with no success.
Here was the .def file for the dll:
With OOP the fb vtable doesn't pass over to c++.
OK if you use only simple OOP with no polymorphism (in general).
I suppose a worthwhile dll to use in c++ is the fb graphics (gfx).
Here I show only three functions from a dll I created in fb, all the functions were tagged export.
I put this dll (graphics.dll) into the same folder as my c++ code.
Here is how I got them in c++.
Code: Select all
#include <windows.h>
#include<stdlib.h>
#include <stdio.h>
typedef void (* thescreen)(int,int,int,int,int);
typedef void (* thedrawstring)(int x,int y,char* text,unsigned int c);
typedef unsigned int ( * thergbcolor)(int r,int g,int b);
thescreen screen;
thedrawstring drawstring;
thergbcolor rgb;
HINSTANCE LB ;
void initgraphics()
{
LB = LoadLibrary(TEXT("graphics.dll"));
if (LB==0)
{
printf("Dll not found\n");
system("pause");
exit(EXIT_SUCCESS);
}
screen = (thescreen) GetProcAddress(LB, "_Z7screen1iiiii");
drawstring = (thedrawstring) GetProcAddress(LB, "_Z10drawstringiiPcj");
rgb= (thergbcolor) GetProcAddress(LB, "_Z8rgbcoloriii");
}
int main()
{
initgraphics();
screen(50,20,1000,768,32);
drawstring(50,10,strdup(" Hello, please close the console by pressing a key . . ."),rgb (255,200,0));
system("pause");
return 0;
}
This was a while back, but I fluffed around to try and use non decorated names with no success.
Here was the .def file for the dll:
Code: Select all
;
; Definition file of graphics.dll
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "graphics.dll"
EXPORTS
_Z10clearcolorj
_Z10drawstringiiPcj
_Z11circlefill1iiij
_Z11screenlock1i
_Z12clearscreen1v
_Z12framecounterv
_Z13screenunlock1i
_Z5line1iiiij
_Z5pset1iij
_Z6sleep1i
_Z7circle1iiij
_Z7dosfonti
_Z7endkey1i
_Z7locate1ii
_Z7randomsi
_Z7screen1iiiii
_Z7waitkeyv
_Z8printdbldi
_Z8regulateiPi
_Z8rgbcoloriii
_Z9getmouse1PiS_S_S_
OK if you use only simple OOP with no polymorphism (in general).
Re: Developing DLLs with FBC?
Hi dodicat,
Could you attach the dll to a file sharing site? Maybe, I can try to create another import library.
Could you attach the dll to a file sharing site? Maybe, I can try to create another import library.
Re: Developing DLLs with FBC?
Here is the dll code, you can compile it yourself.Vortex wrote:Hi dodicat,
Could you attach the dll to a file sharing site? Maybe, I can try to create another import library.
You can delete the .dll.a import file if you like.
Please note: fb 1.08.1 fails with screencontrol so I have commented it out in the sub screen1
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) '' fails with fb 1.08.1
End Sub
sub clearcolor(c as uinteger<32>) export
color ,c
cls
end sub
function rgbcolor(r as integer,g as integer,b as integer) as uinteger<32> export
return rgb(r,g,b)
end function
Sub drawstring (x as integer,y as integer, text As zstring ptr,c as uinteger<32>) 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<32>) 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<32>) export
circle (x1,y1),rad,c,,,,f
end sub
sub circle1(x1 as integer,_
y1 as integer,_
rad as integer,_
c as uinteger<32>) export
circle (x1,y1),rad,c
end sub
sub pset1(x1 as integer,y1 as integer,c as uinteger<32>) 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
sub dosfont(n as integer=16) export
dim as integer x,y
screeninfo x,y
width x\8,y\n
end sub
end extern
Re: Developing DLLs with FBC?
Yes. that's possible. The C header can get auto-translated by fbdoc from FB-*.bi filehungnguyengia wrote:If I don't use any OOP features on FB, could I use this DLL with C easily by just translating the .bi header into .h header? This is what I wanted to know.
-
- Posts: 538
- Joined: Dec 02, 2011 22:51
- Location: France
Re: Developing DLLs with FBC?
Maybe there is also FB Frog to translate from .bi to .h ?... But I don't know if it is stil maintained.
viewtopic.php?f=2&t=28452&p=270618&hili ... og#p270618
added : oups, fbfrog is .h to .bi, perhaps usable as a check tool, or in future as a idea to try to improve automation.
viewtopic.php?f=2&t=28452&p=270618&hili ... og#p270618
added : oups, fbfrog is .h to .bi, perhaps usable as a check tool, or in future as a idea to try to improve automation.
Last edited by Lost Zergling on Aug 01, 2021 12:14, edited 1 time in total.
Re: Developing DLLs with FBC?
Here is a simple dll (including a udt), compiled with fb and used in c++
And here is the c++ code using it (put the dll in the same folder as this c++ code)
All tested fb 1.08 32 bits.
Code: Select all
'udt.bas
'compile with -dll to get udt.dll
extern "C++"
type udt
as double sum
declare function plus(as double,as double) as double
end type
function udt.plus(a as double,b as double) as double export
return a+b
end function
end extern
Code: Select all
#include <windows.h>
#include<stdlib.h>
#include <stdio.h>
struct udt
{
double sum;
double plus(double a,double b);
};
typedef double ( * theplus)( udt* u,double a,double b);
theplus plus;
HINSTANCE LB ;
void init()
{
LB = LoadLibrary(TEXT("udt.dll"));
if (LB==0)
{
printf("Dll not found\n");
system("pause");
exit(EXIT_SUCCESS);
}
plus = (theplus) GetProcAddress(LB, "_ZN3udt4plusEdd");
if (plus==0)
{
printf("plus not found\n");
system("pause");
exit(EXIT_SUCCESS);
}
}//init
int main()
{
init();
udt u;
u.sum=plus(&u,17.5,80);
printf("%f\n",plus(&u,7,8));
printf("%f\n",u.sum);
system("pause");
}
Re: Developing DLLs with FBC?
Hi dodicat,
The problem is the name mangling scheme while linking against the import library. To keep things simple, I decided to create this quick example below :
testdll.bas :
Batch file to build the DLL :
Sample.cpp :
Compiling the 32-bit source code with MinGW :
The import library : libtestdll.dll.a
Result :
Attachment :
https://we.tl/t-JH7OO5PTCn
EDIT : The same method seems to work with FBC 64-bit and MinGW 64-bit.
The problem is the name mangling scheme while linking against the import library. To keep things simple, I decided to create this quick example below :
testdll.bas :
Code: Select all
#ifdef __FB_64BIT__
#define CallConvention
#else
#define CallConvention Cdecl
#endif
function add CallConvention alias "add" (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x+y)
End function
function subs CallConvention alias "subs" (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x-y)
End Function
Code: Select all
REM FreeBASIC Compiler - Version 1.08.1
fbc32 -dll testdll.bas
Code: Select all
#include <stdio.h>
extern "C" {
int add(int x,int y);
int subs(int x,int y);
}
int main()
{
printf("30+10=%d\n",add(30,10));
printf("30-10=%d\n",subs(30,10));
return 0;
}
Code: Select all
REM g++ (MinGW.org GCC-6.3.0-1) 6.3.0
g++ Sample.cpp -o Sample.exe -L. -l testdll -mconsole
Result :
Code: Select all
C:\MinGW32>Sample.exe
30+10=40
30-10=20
https://we.tl/t-JH7OO5PTCn
EDIT : The same method seems to work with FBC 64-bit and MinGW 64-bit.
Re: Developing DLLs with FBC?
Hi dodicat,
Another version :
testdll.bas :
Sample.cpp :
Analyzing testdll.o with Agner Fog's objconv tool :
The FreeBASIC compiler converts to uppercase the public symbols add and subs and the calling convention is __stdcall. This is identified by the statement ret 8, the callee releasing the stack :
The batch files to compile the source codes are the same as above.
Another version :
testdll.bas :
Code: Select all
function add (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x+y)
End function
function subs (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x-y)
End Function
Code: Select all
#include <stdio.h>
extern "C" {
int __stdcall ADD(int x,int y);
int __stdcall SUBS(int x,int y);
}
#define add ADD
#define subs SUBS
int main()
{
printf("30+10=%d\n",add(30,10));
printf("30-10=%d\n",subs(30,10));
return 0;
}
Code: Select all
C:\FreeBASIC>fbc32 -c -dll testdll.bas
C:\FreeBASIC>objconv.exe -fmasm testdll.o Disasm.asm
Input file: testdll.o, output file: Disasm.asm
Converting from COFF32 to Disassembly32
0 Debug sections removed
0 Exception sections removed
The FreeBASIC compiler converts to uppercase the public symbols add and subs and the calling convention is __stdcall. This is identified by the statement ret 8, the callee releasing the stack :
Code: Select all
ALIGN 16
_ADD@8 PROC NEAR
push ebp ; 0030 _ 55
mov ebp, esp ; 0031 _ 89. E5
sub esp, 4 ; 0033 _ 83. EC, 04
mov dword ptr [ebp-4H], 0 ; 0036 _ C7. 45, FC, 00000000
mov eax, dword ptr [ebp+0CH] ; 003D _ 8B. 45, 0C
add eax, dword ptr [ebp+8H] ; 0040 _ 03. 45, 08
mov dword ptr [ebp-4H], eax ; 0043 _ 89. 45, FC
mov eax, dword ptr [ebp-4H] ; 0046 _ 8B. 45, FC
mov esp, ebp ; 0049 _ 89. EC
pop ebp ; 004B _ 5D
ret 8 ; 004C _ C2, 0008
_ADD@8 ENDP
nop ; 004F _ 90
ALIGN 16
_SUBS@8 PROC NEAR
push ebp ; 0050 _ 55
mov ebp, esp ; 0051 _ 89. E5
sub esp, 4 ; 0053 _ 83. EC, 04
mov dword ptr [ebp-4H], 0 ; 0056 _ C7. 45, FC, 00000000
mov eax, dword ptr [ebp+8H] ; 005D _ 8B. 45, 08
sub eax, dword ptr [ebp+0CH] ; 0060 _ 2B. 45, 0C
mov dword ptr [ebp-4H], eax ; 0063 _ 89. 45, FC
mov eax, dword ptr [ebp-4H] ; 0066 _ 8B. 45, FC
mov esp, ebp ; 0069 _ 89. EC
pop ebp ; 006B _ 5D
ret 8 ; 006C _ C2, 0008
_SUBS@8 ENDP
Re: Developing DLLs with FBC?
Hello,
Another test :
testdll.bas :
Sample.cpp :
Another test :
testdll.bas :
Code: Select all
extern "C++"
function add (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x+y)
End function
function subs (Byval x As Integer, Byval y As Integer) as Integer EXPORT
return(x-y)
End Function
End Extern
Code: Select all
\PellesC\bin\podump.exe /Exports testdll.dll
Code: Select all
ordinal hint address name
1 0 10001490 _Z3addll
2 1 100014B0 _Z4subsll
Code: Select all
#include <stdio.h>
extern "C" {
int _Z3addll(int x,int y);
int _Z4subsll(int x,int y);
}
#define add _Z3addll
#define subs _Z4subsll
int main()
{
printf("30+10=%d\n",add(30,10));
printf("30-10=%d\n",subs(30,10));
return 0;
}
-
- Posts: 538
- Joined: Dec 02, 2011 22:51
- Location: France
Re: Developing DLLs with FBC?
Well, I'm not sure about it, I think the expectation is rather about how to convert a .bi to c or c++ .dll but keeping FB code (.bi) coding interface capabilities. I do not know how to achieve this, but it could interest me whenever it'd be hypothetically possible to get better speed ie using lzle (c pointer speed), but I'd be afraid other hand the interface trigger (fine granularity) would also slow down and lost some of the benefits if dynamically linked. Just an exemple and point of view on how I understand specific problematic as describe.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: Developing DLLs with FBC?
With Windows, if you want to write a DLL using FB classes and be compatible with C, C++, and any language that supports pointers and structures, the way is to write a COM server. But, of course, that requires good knowledge of COM programming.
Last year, I posted a template for a low-level COM server.:
viewtopic.php?f=6&t=28599&p=272719#p272716
viewtopic.php?f=6&t=28599&p=272719#p272717
Last year, I posted a template for a low-level COM server.:
viewtopic.php?f=6&t=28599&p=272719#p272716
viewtopic.php?f=6&t=28599&p=272719#p272717
Re: Developing DLLs with FBC?
To capture a simple udt
To use the above .dll in C++
Tested 64 bits.
Or if you are using an ide the command line should include
-L. -l udttest
where the compiled dll (udttest.dll) is in the same folder as the c++ code.
Thanks vortex, I tested out your first code in 64 bits OK.
I cannot see any easy way of calling the dll via code without including windows.h and using LoadLibrary
Code: Select all
'udttest.bas
'compile with -dll to get udttest.dll
extern "C++"
type udt
as double sum
declare function plus(as double) as double
end type
function udt.plus(a as double) as double export
sum=sum+a
return sum
end function
end extern
Code: Select all
// udt2.cpp
#include<stdlib.h>
#include <stdio.h>
struct udt
{
double sum;
double plus(double a);
};
int main()
{
udt u;
u.sum=12;
printf("%f\n",u.plus(8.8));
system("pause");
}
// command line:
//g++ Udt2.cpp -o Udt2.exe -L. -l udttest -mconsole
Or if you are using an ide the command line should include
-L. -l udttest
where the compiled dll (udttest.dll) is in the same folder as the c++ code.
Thanks vortex, I tested out your first code in 64 bits OK.
I cannot see any easy way of calling the dll via code without including windows.h and using LoadLibrary