I need a Visual Studio C++ DLL be able to call a function in my Ada mainline. The Ada code has a function spec like
package offset is
function GET_OFFSET return integer;
pragma Export (Stdcall, GET_OFFSET, "fnAdaOffset");
end offset;
The C++ function then would call the Ada method as follows:
typedef int (*tdAdaOffset)(void);
tdAdaOffset _ptAdaOffset = NULL;
int AdaOffset()
{
if (_ptAdaOffset == NULL)
{
_ptAdaOffset = (tdAdaOffset)GetProcAddress(GetModuleHandle(NULL), "fnAdaOffset@0");
if (_ptAdaOffset == NULL)
throw "Function not found";
}
return (*_ptAdaOffset)();
}
I believe this would work. The problem I have is that Ada refuses to mark the function GET_OFFSET as external in the executable, i.e. doing dumpbin /exports ada.exe shows me no exported functions.
I've read various solutions such as --version-script for the linker , but my linker seems too old to know about this switch.
Another promising option was to add -shared to the link step, but while this now exposes the functions, it also changes the output file to a DLL (with .EXE as its extension (!)), so that's not useful either.
Before I upgrade my toolchain, is there another linker switch I can try, or any other suggestions?
You need to tell the linker to export the symbols from the executable. ld
has an option --export-dynamic
, however that only works on ELF targets:
Note that this option is specific to ELF targeted ports. PE targets support a similar function to export all symbols from a DLL or EXE ; see the description of --export-all-symbols below.
Therefore, on Windows, you need to use --export-all-symbols
.
Depending on how you compile your Ada code, you may need to pass this option through the compiler command (gcc
). To tell gcc
that an option is to be consumed by the linker, you prefix it with -Wl
and then give the linker options separated by commas. In this case, you would end up with -Wl,--export-all-symbols
.
If you're using GPRBuild, the relevant part of your .gpr
file would look like this:
package Linker is
for Default_Switches ("Ada") use ("-Wl,--export-all-symbols");
end Linker;
Side notes:
int
is not necessarily the same as Ada's Integer
and you should use Interfaces.C.int
for the return type in Ada instead.Stdcall
in Ada matches an explicit __stdcall
in C++. If you don't have __stdcall
in the C++ code, use the C
calling convention in Ada instead.