Page 1 of 2
Integrate TinyC libtcc.lib into PureBasic
Posted: Wed Sep 20, 2023 7:32 pm
by JoeC4281
I am running;
PureBasic 6.00 LTS (Windows - x64)
Windows 10 [Version 10.0.19044.3086]
I am a non-expert with many things PureBasic.
I would like to integrate the Tiny C (
https://bellard.org/tcc/)
libtcc.lib (
https://bellard.org/tcc/tcc-doc.html#Libtcc)
into PureBasic.
A search of the PureBasic forums returned one match for libtcc.
idle said on 2022/01/13 that he was looking into libtcc to see if it was usable.
My goal is to create a simple console program that will take
int main(){printf("Hello World.\n"); return 0;}
compile it in memory,
run it,
and have "Hello World" displayed on the console screen.
Yes,
I could use RunProgram (
https://www.purebasic.com/documentation ... gram.html) to run TCC.EXE,
and compile the C-code using that method,
but I would like to learn how to integrate the libtcc.lib into PureBasic,
and run the code that way instead.
The following (incomplete) code is what I have cobbled together,
but it does not work,
as pointers are not my friends.
Code: Select all
EnableExplicit
Global rc.l, s.s
#TCC_OUTPUT_MEMORY = 1
#TCC_OUTPUT_EXE = 2
#TCC_OUTPUT_DLL = 3
#TCC_OUTPUT_OBJ = 4
#TCC_OUTPUT_PREPROCESS = 5
ImportC "libtcc.lib"
; /* compile a string containing a C source. Return -1 If error. */
; LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
tcc_compile_string(*s, *buf) As "tcc_compile_string"
; /* create a new TCC compilation context */
; LIBTCCAPI TCCState *tcc_new(void);
tcc_new() As "tcc_new"
; /* set output type. MUST BE CALLED before any compilation */
; LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
; #define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (Default) */
; #define TCC_OUTPUT_EXE 2 /* executable file */
; #define TCC_OUTPUT_DLL 3 /* dynamic library */
; #define TCC_OUTPUT_OBJ 4 /* object file */
; #define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */ tcc_set_output_type(*s, int) As "tcc_output_type"
tcc_set_output_type(s,i) As "tcc_set_output_type"
; /* link And run main() function And Return its value. DO Not call
; tcc_relocate() before. */
; LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
tcc_run() As "tcc_run"
EndImport
rc.l = tcc_new()
rc.l = tcc_set_output_type(s, #TCC_OUTPUT_MEMORY)
rc.l = tcc_compile_string("int main(){printf("""Hello World.\n"""); return 0;}")
rc.l = tcc_run(s,argc,argv)
For the past couple of days,
I have been reading,
referencing other code I have found in the forum,
but I still cannot grasp what goes where.
I'm coming up on my 61st orbit around the sun,
so any constructive assistance would be appreciated.
Regards and Thanks,
Joe
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Wed Sep 20, 2023 10:48 pm
by infratec
This works ... but with the dll, since I did not found a .lib file
Code: Select all
;
; libtcc.pbi
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
PrototypeC.i Prototype_tcc_new()
PrototypeC Prototype_tcc_delete(*s)
PrototypeC Prototype_tcc_set_lib_path(*s, path.p-Ascii)
PrototypeC Prototype_tcc_error_func(*opaque, msg.p-Ascii)
PrototypeC Prototype_tcc_set_error_func(*s, *error_opaque, error_func.Prototype_tcc_error_func)
PrototypeC Prototype_tcc_set_options(*s, str.p-Ascii)
; preprocessor
PrototypeC.i Prototype_tcc_add_include_path(*s, pathname.p-Ascii)
PrototypeC.i Prototype_tcc_add_sysinclude_path(*s, pathname.p-Ascii)
PrototypeC Prototype_tcc_define_symbol(*s, sym.p-Ascii, value.p-Ascii)
PrototypeC Prototype_tcc_undefine_symbol(*s, sym.p-Ascii)
; compiling
PrototypeC.i Prototype_tcc_add_file(*s, filename.p-Ascii)
PrototypeC.i Prototype_tcc_compile_string(*s, buf.p-Ascii)
; linking
PrototypeC.i Prototype_tcc_set_output_type(*s, output_type.l)
#tcc_OUTPUT_MEMORY = 1
#tcc_OUTPUT_EXE = 2
#tcc_OUTPUT_DLL = 3
#tcc_OUTPUT_OBJ = 4
#tcc_OUTPUT_PREPROCESS = 5
PrototypeC.i Prototype_tcc_add_library_path(*s, pathname.p-Ascii)
PrototypeC.i Prototype_tcc_add_library(*s, libraryname.p-Ascii)
PrototypeC.i Prototype_tcc_add_symbol(*s, name.p-Ascii, val.p-Ascii)
PrototypeC.i Prototype_tcc_output_file(*s, filename.p-Ascii)
PrototypeC.i Prototype_tcc_run(*s, argc.l, *argv)
PrototypeC.i Prototype_tcc_relocate(*s1, *ptr)
#tcc_RELOCATE_AUTO = 1
PrototypeC.i Prototype_tcc_get_symbol(*s, name.p-Ascii)
Global tcc_library.i
Global tcc_new.Prototype_tcc_new
Global tcc_delete.Prototype_tcc_delete
Global tcc_set_lib_path.Prototype_tcc_set_lib_path
Global tcc_set_error_func.Prototype_tcc_set_error_func
Global tcc_set_options.Prototype_tcc_set_options
Global tcc_add_include_path.Prototype_tcc_add_include_path
Global tcc_add_sysinclude_path.Prototype_tcc_add_sysinclude_path
Global tcc_define_symbol.Prototype_tcc_define_symbol
Global tcc_undefine_symbol.Prototype_tcc_undefine_symbol
Global tcc_add_file.Prototype_tcc_add_file
Global tcc_compile_string.Prototype_tcc_compile_string
Global tcc_set_output_type.Prototype_tcc_set_output_type
Global tcc_add_library_path.Prototype_tcc_add_library_path
Global tcc_add_library.Prototype_tcc_add_library
Global tcc_add_symbol.Prototype_tcc_add_symbol
Global tcc_output_file.Prototype_tcc_output_file
Global tcc_run.Prototype_tcc_run
Global tcc_relocate.Prototype_tcc_relocate
Global tcc_get_symbol.Prototype_tcc_get_symbol
Procedure.i tcc_init()
If Not tcc_library
CompilerIf #PB_Compiler_32Bit
tcc_library = OpenLibrary(#PB_Any, "x86\libtcc.dll")
CompilerElse
tcc_library = OpenLibrary(#PB_Any, "x64\libtcc.dll")
CompilerEndIf
If tcc_library
tcc_new = GetFunction(tcc_library, "tcc_new")
tcc_delete = GetFunction(tcc_library, "tcc_delete")
tcc_set_lib_path = GetFunction(tcc_library, "tcc_set_lib_path")
tcc_set_error_func = GetFunction(tcc_library, "tcc_set_error_func")
tcc_set_options = GetFunction(tcc_library, "tcc_set_options")
tcc_add_include_path = GetFunction(tcc_library, "tcc_add_include_path")
tcc_add_sysinclude_path = GetFunction(tcc_library, "tcc_add_sysinclude_path")
tcc_define_symbol = GetFunction(tcc_library, "tcc_define_symbol")
tcc_undefine_symbol = GetFunction(tcc_library, "tcc_undefine_symbol")
tcc_add_file = GetFunction(tcc_library, "tcc_add_file")
tcc_compile_string = GetFunction(tcc_library, "tcc_compile_string")
tcc_set_output_type = GetFunction(tcc_library, "tcc_set_output_type")
tcc_add_library_path = GetFunction(tcc_library, "tcc_add_library_path")
tcc_add_symbol = GetFunction(tcc_library, "tcc_add_symbol")
tcc_output_file = GetFunction(tcc_library, "tcc_output_file")
tcc_run = GetFunction(tcc_library, "tcc_run")
tcc_relocate = GetFunction(tcc_library, "tcc_relocate")
tcc_get_symbol = GetFunction(tcc_library, "tcc_get_symbol")
EndIf
EndIf
ProcedureReturn tcc_library
EndProcedure
Procedure tcc_free()
If tcc_library
CloseLibrary(tcc_library)
tcc_library = 0
EndIf
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
CompilerIf #PB_Compiler_ExecutableFormat <> #PB_Compiler_Console
CompilerError "You need to set the executable format to console in compiler options"
CompilerEndIf
ProcedureC error_func(*opaque, *msg)
Debug PeekS(*msg, -1, #PB_Ascii)
EndProcedure
Define *s, ReturnValue.i
OpenConsole()
If tcc_Init()
*s = tcc_new()
If *s
tcc_set_output_type(*s, #tcc_OUTPUT_MEMORY)
tcc_set_error_func(*s, 0, @error_func())
tcc_add_library_path(*s, "lib")
tcc_add_include_path(*s, "include")
If tcc_compile_string(*s, ~"#include <tcclib.h>\n int main(){\n printf(\"Hello World.\n\");\n return 0;\n}\n") <> -1
ReturnValue = tcc_run(*s, 0, #Null)
Debug "Returned: " + Str(ReturnValue)
EndIf
tcc_delete(*s)
Else
Debug "Could not create tcc state"
EndIf
tcc_free()
Else
Debug "Not able to load dll"
EndIf
PrintN(#LF$ + "Press RETURN to end")
Input()
CompilerEndIf
If you create the directories lib and include and put the reqired files inside,
it compiles and run without errors.
You have to compile it as Console application, then you can see the output in the console window.
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 10:27 am
by infratec
To be clear:
The directory structure should look like this:
[include] -> tcclib.h, stddef.h, stdarg.h, ...
[lib] -> libtcc1-32.a, libtcc1-64.a
[x64] -> libtcc.dll
[x86] -> libtcc.dll
libtcc.pbi
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 12:39 pm
by chi
Great work, infratec! You could also create an import lib from the def file and use it like this...
Code: Select all
; polib.exe /MACHINE:x64 /DEF:libtcc.def /OUT:libtcc.lib
CompilerIf #PB_Compiler_ExecutableFormat <> #PB_Compiler_Console
CompilerError "You need to set the executable format to console in compiler options"
CompilerEndIf
ImportC "libtcc.lib"
tcc_new.i()
tcc_set_output_type.i(*s, output_type.l)
tcc_compile_string.i(*s, buf.p-Ascii)
tcc_run.i(*s, argc.l, *argv)
tcc_delete(*s)
EndImport
*s = tcc_new()
tcc_set_output_type(*s, 1)
tcc_compile_string(*s, ~"int printf(const char *format, ...);\n\n int main(){\n printf(\"Hello World.\n\");\n return 0;\n}\n")
tcc_run(*s, 0, #Null)
tcc_delete(*s)
CallDebugger
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 1:04 pm
by infratec
But then you need to copy the right dll in the main directory.
Code: Select all
;
; libtcc_lib.pbi
;
; you have to use the correct libtcc.def file
; x86>c:polib.exe /MACHINE:x86 /DEF:libtcc.def /OUT:libtcc.lib
; x64>c:polib.exe /MACHINE:x64 /DEF:libtcc.def /OUT:libtcc.lib
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
#tcc_OUTPUT_MEMORY = 1
#tcc_OUTPUT_EXE = 2
#tcc_OUTPUT_DLL = 3
#tcc_OUTPUT_OBJ = 4
#tcc_OUTPUT_PREPROCESS = 5
#tcc_RELOCATE_AUTO = 1
PrototypeC Prototype_tcc_error_func(*opaque, msg.p-Ascii)
CompilerIf #PB_Compiler_32Bit
ImportC "x86\libtcc.lib"
CompilerElse
ImportC "x64\libtcc.lib"
CompilerEndIf
tcc_new.i()
tcc_delete(*s)
tcc_set_lib_path(*s, path.p-Ascii)
tcc_set_error_func(*s, *error_opaque, error_func.Prototype_tcc_error_func)
tcc_set_options(*s, str.p-Ascii)
; preprocessor
tcc_add_include_path.i(*s, pathname.p-Ascii)
tcc_add_sysinclude_path.i(*s, pathname.p-Ascii)
tcc_define_symbol(*s, sym.p-Ascii, value.p-Ascii)
tcc_undefine_symbol(*s, sym.p-Ascii)
; compiling
tcc_add_file.i(*s, filename.p-Ascii)
tcc_compile_string.i(*s, buf.p-Ascii)
; linking
tcc_set_output_type.i(*s, output_type.l)
tcc_add_library_path.i(*s, pathname.p-Ascii)
tcc_add_library.i(*s, libraryname.p-Ascii)
tcc_add_symbol.i(*s, name.p-Ascii, val.p-Ascii)
tcc_output_file.i(*s, filename.p-Ascii)
tcc_run.i(*s, argc.l, *argv)
tcc_relocate.i(*s1, *ptr)
tcc_get_symbol.i(*s, name.p-Ascii)
EndImport
CompilerIf #PB_Compiler_IsMainFile
CompilerIf #PB_Compiler_ExecutableFormat <> #PB_Compiler_Console
CompilerError "You need to set the executable format to console in compiler options"
CompilerEndIf
ProcedureC error_func(*opaque, *msg)
Debug PeekS(*msg, -1, #PB_Ascii)
EndProcedure
Define *s, ReturnValue.i
OpenConsole()
*s = tcc_new()
If *s
tcc_set_output_type(*s, #tcc_OUTPUT_MEMORY)
tcc_set_error_func(*s, 0, @error_func())
tcc_add_library_path(*s, "lib")
tcc_add_include_path(*s, "include")
If tcc_compile_string(*s, ~"#include <tcclib.h>\n int main(){\n printf(\"Hello World.\n\");\n return 0;\n}\n") <> -1
ReturnValue = tcc_run(*s, 0, #Null)
Debug "Returned: " + Str(ReturnValue)
EndIf
tcc_delete(*s)
Else
Debug "Could not create tcc state"
EndIf
PrintN(#LF$ + "Press RETURN to end")
Input()
CompilerEndIf
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 1:28 pm
by JoeC4281
chi wrote: Thu Sep 21, 2023 12:39 pm
Great work, infratec! You could also create an import lib from the def file and use it like this...
Code: Select all
; polib.exe /MACHINE:x64 /DEF:libtcc.def /OUT:libtcc.lib
Instead of creating my own
libtcc.lib,
I used the
.lib that comes with Tiny C,
compiled your code, and success.
Thankyou,
chi, for your help.
Thanks also to
infratec for his alternate method, using the
.dll
Joe
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 2:19 pm
by Little John
Hi, I've got a question just out of curiosity:
Since version 6.0 PureBasic has a C backend, which AFAIK also can be used directly. What is the advantage of using another C compiler, such as TinyC?
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 3:45 pm
by Jeromyal
Little John wrote: Thu Sep 21, 2023 2:19 pm
Hi, I've got a question just out of curiosity:
Since version 6.0 PureBasic has a C backend, which AFAIK also can be used directly. What is the advantage of using another C compiler, such as TinyC?
I was wondering that myself, however TCC has the ability to compile and run code directly in memory. That is how CToy works with TCC.
So, I myself would create TCC inegration with my own CToy like editor in PureBasic. Edit > Run in ram > or compile as application from a nice interface.
That being said, I do not know if gcc can't also compile and execute in ram. I have not bothered to look it up yet.
edit:
Actually I may be wrong about compiling and running c code in memory. There is more like a runtime involved. But CToy has some sort of ability for the user to create persistent memory space to preserve information between code changes. TCC is a fast little compiler so it is understandable that CToy was thus birthed.
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 4:21 pm
by infratec
PB code is fixed, you can not change it after compile time.
With libtcc or lua or ... you can modify and run the code at runtime.
Or read it from a file or use code from an EditorGadget()
Or ...
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 6:46 pm
by chi
JoeC4281 wrote: Thu Sep 21, 2023 1:28 pm
Instead of creating my own libtcc.lib,
I used the .lib that comes with Tiny C
There is no .lib in tcc-0.9.27-win64-bin.zip
Little John wrote: Thu Sep 21, 2023 2:19 pm
Hi, I've got a question just out of curiosity:
Since version 6.0 PureBasic has a C backend, which AFAIK also can be used directly. What is the advantage of using another C compiler, such as TinyC?
Different compilers have different optimizations... It's quite fun to play around, compare and finally deliver the best performing exe.
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 7:12 pm
by JoeC4281
chi wrote: Thu Sep 21, 2023 6:46 pm
There is no .lib in tcc-0.9.27-win64-bin.zip

You are correct.
I checked the date on
libtcc.lib,
and it would appear that I created libtcc.lib a while back.
Now that I have a working console app,
I hope to create a plugin (
https://jpsoft.com/all-downloads/tcc-plugins.html),
integrating TinyC into Take Command Console,
so that it is usable from the console for C one-liners,
or simple scripts that can be made hybrid with .BTMs
Joe
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 8:20 pm
by idle
@ infratec and @chi
You're both legends.
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 8:52 pm
by Patrice Terrier
Hello
I am not a PureBasic programmer, however I have used TClib.lib with success, and I was able to produce very small binary executable using it.
There is a dedicated section on my private forum here
http://www.objreader.com/index.php?board=19.0
anf here is a C++ 64-bit GDImage tutor producing a binary of only 27 Kb using TCLib.lib
http://www.objreader.com/index.php?topi ... 75#msg6375
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 9:45 pm
by idle
Hi Patrice
We're not stopping you from becoming a purebasic programmer.

(Didn't you make opengl tlb for vb6 back in the day?)
Re: Integrate TinyC libtcc.lib into PureBasic
Posted: Thu Sep 21, 2023 11:08 pm
by Patrice Terrier
idle
No, I don't want to become a purebasic programmer, because I am using only the low level procedural SDK API, that is the only common denominator understood with the different languages I am using.
I never worked with VB6.
About OpenGL I wrote my own 3D engine, and many audio visual plugins.
Here is my Behance page showing some wavefront .obj 3D models designed specifically for my ObjReader freeware.
https://www.behance.net/pterrier948d
All models have been created or reworked with Maxon C4D, to use my specific ObjReader shader.