Exporting procedures when compiling against static library
Posted: Sun May 11, 2025 1:54 pm
I wonder if this is possible with PureBasic, the idea is that create a static library in another language and to compile that with PureBasic to a binary and avoid any extra dynamic dll files. The static library exports functions that PureBasic imports but the static library also imports procedures that PureBasic exports.
I will use dlang and the dmd compiler (ldc2 works as well) to test this. We will compile our dlang code with the betterC flag to avoid any GC stuff.
We will begin to test dlang -> pb with a static library
myfunc.d
We compile this to a obj file with dmd (we use -m64 flag to get COFF format) and then we use polib (from PureBasic installation) to create lib file
We import addNumbers() to pb
main.pb
This should say 7 in the message requester, thus we can create a standalone binary from a static library.
The next step is to export a procedure from pb to dlang to test pb -> dlang
mylib.pb
This will produce mylib.dll and mylib.lib as a dynamic library.
main.d
This will create a maind.exe, when running it should say 70. (maind.exe binary requires mylib.dll to be present.)
Now we want to test pb -> dlang ->pb
However this time we shouldn't be using our mylib.dll, it ought to be possible to export our multiplier procedure during compile time that the static lib can use
myfunc.d
main.pb
The linker can't find the multiplier symbol. How can we make sure to export multiplier() during compile time so that the static library myfunc.lib works?
I have tested to export with ProcedureC but that didn't make any difference.
I will use dlang and the dmd compiler (ldc2 works as well) to test this. We will compile our dlang code with the betterC flag to avoid any GC stuff.
We will begin to test dlang -> pb with a static library
myfunc.d
Code: Select all
module myfunc;
extern(C) export int addNumbers(int a, int b)
{
return a + b;
}
Code: Select all
dmd -betterC -m64 -c myfunc.d
polib /out:myfunc.lib myfunc.obj
main.pb
Code: Select all
Import "myfunc.lib"
addNumbers.l(a.l, b.l)
EndImport
Define result = addNumbers(5, 2)
MessageRequester("Result", "D addNumbers(): " + Str(result))
Code: Select all
pbcompiler main.pb
The next step is to export a procedure from pb to dlang to test pb -> dlang
mylib.pb
Code: Select all
ProcedureDLL.l multiplier(value.l)
ProcedureReturn value * 10
EndProcedure
Code: Select all
pbcompiler /dll mylib.pb /output mylib.dll
main.d
Code: Select all
extern(C) int multiplier(int value);
int addNumbers(int a, int b)
{
int sum = a + b;
int result = multiplier(sum);
return result;
}
extern(C) int main()
{
import core.stdc.stdio : printf;
int r = addNumbers(2, 5);
printf("Result: %d\n", r);
return 0;
}
Code: Select all
dmd -betterC main.d mylib.lib -L/subsystem:console -of=maind.exe
Now we want to test pb -> dlang ->pb
However this time we shouldn't be using our mylib.dll, it ought to be possible to export our multiplier procedure during compile time that the static lib can use
myfunc.d
Code: Select all
module myfunc;
extern(C) int multiplier(int value);
extern(C) export int addNumbers(int a, int b)
{
int sum = a + b;
return multiplier(sum);
}
Code: Select all
dmd -betterC -m64 -c myfunc.d
polib /out:myfunc.lib myfunc.obj
Code: Select all
ProcedureDLL.l multiplier(value.l)
ProcedureReturn value * 10
EndProcedure
Import "myfunc.lib"
addNumbers.l(a.l, b.l)
EndImport
Define result = addNumbers(5, 2)
MessageRequester("Result", "D addNumbers(): " + Str(result))
Code: Select all
pbcompiler main.pb
Code: Select all
PureBasic 6.20 (Windows - x64)
Compiling main.pb
Loading external libraries...
Starting compilation...
12 lines processed.
Creating and launching executable.
Error: Linker
error: undefined symbol: multiplier
>>> referenced by myfunc.lib(myfunc.obj):(addNumbers)
I have tested to export with ProcedureC but that didn't make any difference.