0

Is it possible to create/generate a pointer declaration similar to:

void (*foo)(int, float);

bool (*foo)();

char (*foo)(char, int);

But without knowing the type of the arguments or the return type until run-time.

The function declaration would be read from a string which would specify the return and argument type (if any) then (if possible) stored in a c++ container.

Can it be done at run-time (not compile-time) ? And also C++11 can be used if necessary.

I really doubt this can be done in a statically typed language like C++ but if it can be done then what approach would someone use. No need for code (but it's appreciated) just some guidance to what must be used.

EDIT:

After testing several ideas it turns out that it can't be achieved (directly) with C++. Luckily I found the dyncall library which allows me do do it (indirectly) and on a quite large number of platforms.

Example function:

double sqrt(double x);

Using dyncall to call the function:

double r;
DCCallVM* vm = dcNewCallVM(4096);
dcMode(vm, DC_CALL_C_DEFAULT);
dcReset(vm);
dcArgDouble(vm, 4.2373);
r = dcCallDouble(vm, (DCpointer)&sqrt);
dcFree(vm);

Strings can also be used to declare the structure of a function.

C function prototype                                dyncall signature

void f1();                                          ")v"
int f2(int, int);                                   "ii)i"
long long f3(void*);                                "p)L"
void f3(int**);                                     "p)v"
double f4(int, bool, char, double, const char*);    "iBcdZ)d"
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
SLC
  • 2,167
  • 2
  • 28
  • 46
  • As far as I know, this can't be done. – R Sahu Mar 25 '14 at 01:24
  • So you have a string. You store *something* in a container that is derived from that string in some way (it can't be a declaration - that's a compile-time notion; you would be storing some object). Now what? What is the ultimate goal of this exercise? – Igor Tandetnik Mar 25 '14 at 01:26
  • Why do you need to do this? Is it possible to redesign your code so you don't need to do it? – cup Mar 25 '14 at 01:29
  • I need to be able to generate a function pointer declaration for use with AsmJit for a small scripting language that needs to support simple functions. AsmJit can assign generated code to function pointers which can then be called from c/c++. Nothing out of the ordinary just the basic c++ types will be used. No objects or anything of that sort. Maybe pointers but other than that nothing else would be used for arguments. – SLC Mar 25 '14 at 01:32
  • No. Make the function take container of Variants (where "Variant" is an object that can contain various types of data). – M.M Mar 25 '14 at 02:50

2 Answers2

2

It depends how many types of arguments you will handle. Technically - you can do everything in C++, just sometimes it's not as simple as you would want it to be.

You could use the delegate pattern:

class baseDelegate(){};

template<typename retT, typename paramT>
class delegate: public baseDelegate{
    public:
    retT (*ptr)(paramtT);
};

vector<baseDelegate*> yourDelegateList;

Since you tagged the topic as C++11, you could also use std::function, variadic templates and so on, to make it easier. The above code is just an example.

Paweł Stawarz
  • 3,952
  • 2
  • 17
  • 26
  • Yes but std::function also needs it's definition at compile time std::function. I thought of using that and then extract the function definition from the std::function::target_type member. – SLC Mar 25 '14 at 01:35
  • I browsed a little and I think I might be able to do it with std::tuple. Simply construct a std::tuple with my values using std::make_tuple and then use std::tuple_element to extract the type of the elements and use them to generate an std::function. I'll try it later and see if it works unless someone else comes with a proven solution. – SLC Mar 25 '14 at 01:43
  • It would be much easier to do if you could ensure all types passed as arguments are either built-in or derived from one base class. While using the delegate pattern you have to know all the possible combinations of both the return type and parameter types, but I don't think you can find anything more flexible. – Paweł Stawarz Mar 25 '14 at 01:52
  • I won't be using anything else other then the basic C++ data types and pointers therefore I think it might work with tuples. Not to mention that the argument number is locked at 16. So, no more then 16 arguments and one return type. I'll just need to build a container similar to std::vector that can hold multiple types of data. I'll do this using your idea of "derived from one base class" and simply construct an std::tuple based on the size of the container. Hopefully it might actually work :) – SLC Mar 25 '14 at 02:00
  • After testing several ideas it turns out that you can't :( It's almost impossible. – SLC Mar 25 '14 at 19:47
  • @SanduLiviuCatalin you can also combine `boost::any` with variadic templates. Maybe that'll be better in your case. Thought about it just now TBH. – Paweł Stawarz Mar 25 '14 at 19:49
  • I found the dyncall library which does it automatically for me :) – SLC Mar 25 '14 at 19:56
0

You could doe something like

void function (string &arg, …) ;

and use the variable arguments feature of C++.

You need at lest one fixed argument though.

Generally, what you are describing is not a good thing in C++ as you indicate.

user3344003
  • 20,574
  • 3
  • 26
  • 62