Using pragma Convention without export - export

I need to use the Ada library from Lua. I want to use a generic package, which, along with other data, will contain a function that will register in Lua with different names depending on the data. As I understand it, I should declare this function as "with Export, Convention => C", but when instantiating several instances of such a package, the library will contain several functions with the same names and it will not compile. Is it possible in such a situation not to use "Export", but only the "Convention => C", because only a function reference is used for registration in Lua?
with System; use System;
with Interfaces.C; use Interfaces.C;
generic
type Data is private;
Name : String;
package P is
function Call (Lua : Address) return int
with Export, Convention => C;
function Get_Name return String is (Name);
end P;

You only need Export if the function needs to be visible to a linker (for example, when you have C code explicitly calling this function). If you only need to pass the function via pointer into the Lua runtime, Convention => C on the function suffices, though you also need another Convention => C on the function pointer type.

Related

Call function only knowing parameter types at runtime in C?

Let's say I have a function:
int foo (int A, char B){...}
One of the features I want to implement is the capability for the user to call any function on the application through the Linux terminal. So as an input for the software, in the terminal they type something like:
foo 2 'a'
Then my application parses that, and using the symbol tables it is able to find the address for foo(), as well as the type for all its parameters.
However, I'm not sure how I would pass the parameters to the function when calling it, since I can have hundreds of different parameters types combination depending on the function called.
Any hint how that could be achieved without having hundreds of nested if statements to cast the parameters to the correct types before calling the functions?
That functionality is similar to what GDB has, where you can do call foo(2,'a') and GDB calls that function to you.
There are two approaches to this. If what you described is all you want to do, then you can use the dyncall library so that you dont have to worry about platform/compiler-specific calling semantics yourself:
The dyncall library encapsulates architecture-, OS- and compiler-specific function call semantics in a virtual bind argument parameters from left to right and then call interface allowing programmers to call C functions in a completely dynamic manner. In other words, instead of calling a function directly, the dyncall library provides a mechanism to push the function parameters manually and to issue the call afterwards.
The other approach is, if you might want to do more: e.g. what if an argument cannot be created by a literal? What if the argument is the output of another function? Can you write f(123, g("a")) in your console? Can you write x=g("a"); f(x)? And if(cond) x="a" else x="b"; f(x) In this case you need to embed a scripting language like e.g. LUA.
If you compile your binary with debug information, you can extract it using libdwarf (https://www.prevanders.net/dwarf.html), so for every function you can get a list a parameters with types and you would know how to interpret user's input.

c programming language - declare() function

I am writing a c program and came across the declare() function.
When I searched on web for it, I received results about function declaration and function definition.
I would like to know about the declare() function in c,what it does, what are its parameters, etc.
Here is block of code that uses the function:
char file[50];
strcpy(file,"IS_inst.txt");
declare(file,IS_ins,&IS_inst_count);
strcpy(file,"DS_inst.txt");
declare(file,DS_ins,&DS_inst_count);
strcpy(file,"AD_inst.txt");
declare(file,AD_ins,&AD_inst_count);
strcpy(file,"REG_OPERAND.txt");
declare(file,REG_oprand,&REG_op_count);
There is no such function in C, it might/should be defined in your program.
There is no function called declare in the C standard library, or, as far as I know, in any commonly used add-on library.
There's nothing special about the name declare. It might as well have been named foobar.
It must be declared as a function or as a macro somewhere in your program. If your development environment has such a feature, try querying the name (perhaps you can hover over or right-click on the function name if you're using an IDE). Or just search the source file and any headers it #includes for the name declare. grep and ctags are both useful tools for this kind of thing.
You should implement this function in your code
Declare function means you are assigning a function's return type. There is no built in function named as "Declare Function". Suppose, you want to create a function to add numbers. So, you can name the function as "Add". In c programming you have to declare the function type at first example: for two integers addition the function type should be int Add() {}

Variadic function in Ada (C - Ada binding)?

I am working on a project which uses C - Ada language binding. A function in C will call a function in Ada side. I want to make a variadic function in Ada which can receive a variable number of arguments sent from the C function. I also wanted to send different types of args at the same time like int, char, enums, etc at the same time. Is it possible to have this type of mechanism?
The forthcoming Ada standard Ada 202x is planning to provide support for calling C variadic functions.
You would then be able to write;
package C renames Interfaces.C;
procedure Printf (Format : in C.char_array)
with Import => True, Convention => C_Variadic_1, External_Name => "printf";
You cannot create a variadic function in Ada. You can simulate a variadic function is a couple of ways.
Ada allows you to specify default values for functions and procedures. One need not always specify the values of the default parameters if you want to use the default values.
You can define one or more of the parameters as a variant record.
It is not possible to call any C variadic function from Ada in a portable way!
One of the reason - some ABIs use special ways/registers to pass float values. This mean C compiler will use this registers, due to it's unknown in advance whether argument is float or not. Ada compiler will not use this registers (since you can't put float parameter in Ada wrapper function declaration). As result you will get crash, stack corruption or any other undefined behavior.
Particularly AMD64 ABI specifies:
%rax - with variable arguments passes information
about the number of vector registers used
%xmm0–%xmm1 - used to pass and return floating
point arguments
The only portable solution is using C wrapper with fixed number of parameters, then bind it as usual.
You can use 'address or the package System.Address_To_Access_Conversions and 'access (or 'unchecked_access) to generate addresses of each item you want to pass.
type Address_Array is array (positive range <>) of System.address;
function C_Caller(Params : Address_Array) return Integer is begin return 0; end;
X, Y, Z, Result : Integer;
begin
result := C_Caller(Address_Array'(x'address, y'address, z'address));
...then you'll need to pragma import the actual function.

Function-Pointer in Interpreter

I am building a C-Interpreter (in C++) which builds an AST. I want to give the user the opportunity to communicate with real DLLs. For example: I call a function from a DLL. This function expects an pointer to an function (to callback). There is the problem: I don't have a real address to a function, because the function which I want to give to the DLL-function only exists as node in my AST. Is there a way to solve the problem? I thought about using a proxy-like function built-in into my interpreter, which delegates to the function in my AST. The problem is, that the proxy-function must have the same signature to be callable from the DLL-function ... and i can't create dynamic functions at runtime.
You don't say specifically which API/dll you're trying to use, but MOST of them provide for a void * (or LPVOID on windows) of 'user data' that is supplied along with the callback function pointer and will be passed to the callback function, along with whatever other arguments are appropriate for the callback.
What you can do is pass in a pointer to your AST as this extra pointer, and write a small wrapper function for the actual callback which converts this void * back into an AST * and then invokes your interpreter on that AST.

How to get function address by name?

I'd like to get function's address by name.
For example, currently I am using dlsym:
unsigned long get_func_addr(const char *func_name)
{
return (unsigned long)dlsym(NULL, func_name);
}
However, dlsym only works for extern function. It won't work for static function. I know there could multiple static functions with same name in different files. But I need to at least get one static function's address with the name. Sometime static function will be inlned. But it's OK if C file is compiled with debug. I think with -g, the symbol table of static functions is present, but how can I access it?
I don't want to created a table for mapping the string to function address. I need to find a way to do it dynamically.
This isn't really possible without somehow creating some external file that can be used for a look-up ... for instance, as you mentioned, a symbol table of static functions is present, but that is generated at compile/link time ... it is not something accessible from a non-compiled code module.
So basically you could generate and export the symbol table as an external file from your compiled and linked executable, and then have a function that dynamically looks up the function name in the external file which would provide the information necessary to get the address of the function where the complier and linker compiled/linked it to.
A static function need not even exist in the binary, so there's no way to get its address. Even if it does exist, it might have been modified by the compiler based on the knowledge that certain arguments can only take particular values, or it might have had the calling convention adjusted such that it's not externally callable, etc. The only way you can be sure a "real" version of a static function exists is if its address is made visible to other modules via a function pointer.
If the required function you want to lookup is in a DLL, you could use the Windows API getprocaddress(), which takes the name of the function and the name of the DLL as parameters.
If you want to find user defined functions, I would recommend using a lookup table as the names of those functions are not stored.
For user defined functions, you could force that every function export its name to another function at its start. i.e.:
void my_func()
{
register(my_func,"my_func");// the address and the name
// ...
}
Thus you could lookup the function later by name.

Resources