There is a way in C to obtain a dynamic length argument list with va_list, as described here:
http://www.cprogramming.com/tutorial/c/lesson17.html
That quite simple, but most times in C++ not needed. I am currently building a top level wrapper class for encapsulating some Zend functionality.
Anyway, I do need to make a call to such a dynamic function like printf from a normal function dynamically.
I mean the reverse way of the example described above, here is waht I got so war, maybe this explains my idea a little better:
void ZendParams::setRequired( int &Var )
{
// save every var pointer to a stack
// and save the type with it. (if needed, does not seems to be)
// after call to ZendParams::fetch()
// the values are stored in the passed variables
this->_params.push_back( (void*) &Var );
this->_paramStr.append( 'i' );
}
size_t ZendParams::fetch()
{
if ( zend_parse_parameters(
ZEND_NUM_ARGS() TSRMLS_CC, ,
this->_paramStr.c_str(),
...
) !== FAILURE)
{
}
return 0;
}
So I want to make the call to zend_parse_parameters dynamically.
The base idea is to add pointer to vars in a list and pass them to the zend function (as reference) dynamically.
I thought there must be a way to do this with va_list , too.
But how?
To get it more simple, I am using this example:
list<int> myList;
myList.push_back(1);
myList.push_back(5);
myList.push_back(10);
myList.push_back(37);
myList.push_back(42);
double function avg( int num, ... )
va_list arguments;
int sum = 0;
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
sum += va_arg ( arguments, int );
}
va_end ( arguments );
return sum / num;
}
I want to call avg with all numbers I got in the list. I took the example function from the tutorial mentioned above, but it should show up what I mean in a very simple way.
However, I can not change the function called, as it is part of the zend framework.
Is there any way in C or C++ to do this?
My 2nd approach:
template <typename... Arguments>
size_t Zend::getMethodParams( string paramStr, Arguments... Args )
{
if ( zend_parse_parameters(
ZEND_NUM_ARGS() TSRMLS_CC, ,
paramStr.c_str(),
Args...
) == FAILURE)
{
return 0;
}
}
To be called like this (to get the defined 3 Parameters):
string My1stParam;
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam, &My2ndParam, &My3rdParam );
I think that should work, but there is one hard issue with that:
The zend_parse_parameters function returns 2 values for a string (c-style string!):
- a char pointer and
- the string length.
So I would either have to call it that way:
char* My1stParam_str;
int My1stParam_length
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam_str, &My1stParam_length, &My2ndParam, &My3rdParam );
string My1stParam;
My1stParam.assign(My1stParam_str, My1stParam_length);
Anyway, that was what I wanted to prevent.
Or I would have to modify the list of arguments passed to the zend_parse_parameters function to do these additional steps internally.
I am hoping to be able to call it at least in that way:
string My1stParam;
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam, &My2ndParam, &My3rdParam );
So say this clearly: The parameters are known at compile time, but the function call will be very different within all occurrences in the later sourcecode.
I found a way around this within the zend framework. I did indeed search for such a solution before, but it seems to be not very good documented ( n.m. already mentoined, that there is no zend internal way like a va_list taking function ).
But there is indeed one!
For everyone else stucking with this problem:
long arg;
zval ***args;
int i, argc = ZEND_NUM_ARGS( );
if (zend_parse_parameters(1 TSRMLS_CC, "l", &arg) == FAILURE) return;
array_init(return_value);
add_index_long(return_value, 0, arg);
if(argc>1) {
args = (zval ***)emalloc(argc * sizeof(zval **));
if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
efree(args);
return;
}
for(i = 1; i < argc; i++) {
zval_add_ref(args[i]);
add_index_zval(return_value,i, *args[i]);
}
efree(args);
}
That is the solution ;)
This snippet, found on http://docstore.mik.ua/orelly/webprog/php/ch14_07.htm parses all parameters dynamically into the c representation of an PHP array.
Related
I remember vaguely that python allowed something like
def foo( x ):
....
f = foo( 5 )
Is something like that possible in c++ so that if I have a member function
class C {
void foo( int x ) { ... }
so that I can define a pointer or variable that would effectively point at foo( 5 )
The reason why I want to do this is because I have many listeners that I need to subscribe to a callback and keep information who gets called
class C {
map<int, ptrSender> m_sender;
void subscribe() {
for (const auto& p : m_sender) {
p .second->register( Callback( this, &C::onCall ) )
}
My problem is that the onCall does not return which sender called back, but I would need this information. So, instead of doing something like this
void subscribe() {
m_sender[0]->register( Callback( this, onCall_0 ) );
m_sender[1]->register( Callback( this, onCall_1 ) );
....
void onCall( int sender_id ) { ... }
void onCall_0() { onCall( 0 ); }
void onCall_1() { onCall( 1 ); }
....
I was hoping I could pass something into register that would return a call with a preset argument. Is this possible?
EDIT: I am trying to use a lambda function, but I am running into the following problems
auto setCall= [this]( int v ) { &C::onCall( v ); }
gives the compile error
lvalue required as unary&opeand
This
auto setCall= [this]( int v ) { C::onCall( v ); }
....
p.second->register( Callback( this, &setCall( p.first) ) ); /// <__ error now here
complains again, now in the second line
lvalue required as unary&operand
and this
auto setCall= [this]( int v ) { C::onCall( v ); }
....
p.second->register( Callback( this, setCall( p.first) ) ); /// <__ error now here
complains about invalid use of void expression, but I assume I have to pass in a reference to make the register function happy
Callback seems to be defined as
# define CallBack(obj,func) ProfiledBasicCallBack(obj,fastdelegate::FastDelegate0<void>(obj,func),#func)
Yes, you can use std::bind. Example usage: http://ideone.com/akoWbA.
void foo( int x ) { cout << x << endl; }
auto x = std::bind(foo, 5);
x();
However, with modern C++, you should use a lambda. Like so:
void foo( int x ) { cout << x << endl; }
auto x = []() { foo(5); };
x();
Note that this foo function is outside of the class C in this example. If you wish to contain it inside, then with std::bind you need to pass the instance of the object you wish to call on, e.g.
C c;
auto x = std::bind(&C::foo, &c, 5);
x();
or with lambdas:
C c;
auto x = [&c]() { c.foo(5); };
x();
What you are looking for is std::bind(). It takes one callable object, and gives you another callable object with predefined values for its parameter, and maybe some optional parameters forwarded to it.
A word of warning: this is a fairly steep learning curve. You need to understand templates.
If you want to bind a parameter value to a compile-time constant argument (like 5 in your example), then the problem can be solved by introducing a simple wrapper function that will call your function while passing the desired constant values as corresponding arguments.
But when the argument is a run-time value, then the answer is no: it is generally not possible to create a credible implementation of such function pointer binding in C++ (unless you are using some compiler-specific extension).
However, in C++ you have a variety of alternative tools at your disposal. You can create a function object that will mimic the functionality you desire. Such function object can be created by using std::bind, by using lambda-expressions, or even implemented manually.
The resultant function object will be "callable" and will behave similarly to function pointer at superficial level, but nevertheless it won't be a function pointer, won't be convertible to a function pointer and won't be accepted where a genuine function pointer is required. In other words, if your register method is declared to expect a function pointer as its second argument, then there's nothing you can do here. Neither std::bind, nor lambdas, nor anything else in the language will help you to achieve this kind of parameter binding.
For this reason it is generally a good idea to steer clear of function pointers in such designs and implement such functionality in terms of generic callable objects. The simplest thing to use might be std::function objects in place of raw function pointers.
I have the following situation.
I need to insert certain CallInst in my code.
The prototype of my function is
void __llvmFooBar(int data, int loc);
The parameter loc is generated by the pass. I don't need any external data to generate that.
But, the parameter data is basically calculated by using some variable declared inside my C-code.
//test.c
int main()
{
int k = 0;
happyEnding(k);
}
void happyEnding(int k)
{
int __data = seed(time()) + k%2;
//callInst to be inserted here, it should be
//__llvmFooBar(__data, 23);
myAlgorithim();
}
//pass.cpp
......
std::vector<Value *> args(2);
args[0] = ??? //need help here
args[1] = ConstantInt::get(IntegerTy, getLoc());
m_builder->CreateCall(hook, args);
In generic sense, how to make all variable with specific naming convention(like starts with __) make available to llvm pass ?
I am trying to write a native C++ module to include in a Node.js project -- I followed the guide here and have things setup pretty well.
The general idea is that I want to pass an array of integers to my C++ module to be sorted; the module then returns the sorted array.
However, I cannot compile using node-gyp build because I hit the following error:
error: no viable conversion from 'Local' to 'int *'
It is complaining about this code in my C++:
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
int* inputArray = args[0]; // <-- ERROR!
sort(inputArray, 0, sizeof(inputArray) - 1);
args.GetReturnValue().Set(inputArray);
}
This all makes conceptual sense to me -- the compiler can't magically cast arg[0] (presumably of type v8::Local) to an int*. Having said that, I cannot seem to find any way to get my argument successfully cast into a C++ integer array.
It should be known that my C++ is rather rusty, and I know next-to-nothing about V8. Can anyone point me in the right direction?
It's not trivial: you first need to unpack the JS array (internally represented as a v8::Array) into something sortable (like a std::vector), sort it, and convert it back to a JS array.
Here's an example:
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
// Make sure there is an argument.
if (args.Length() != 1) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Need an argument")));
return;
}
// Make sure it's an array.
if (! args[0]->IsArray()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "First argument needs to be an array")));
return;
}
// Unpack JS array into a std::vector
std::vector<int> values;
Local<Array> input = Local<Array>::Cast(args[0]);
unsigned int numValues = input->Length();
for (unsigned int i = 0; i < numValues; i++) {
values.push_back(input->Get(i)->NumberValue());
}
// Sort the vector.
std::sort(values.begin(), values.end());
// Create a new JS array from the vector.
Local<Array> result = Array::New(isolate);
for (unsigned int i = 0; i < numValues; i++ ) {
result->Set(i, Number::New(isolate, values[i]));
}
// Return it.
args.GetReturnValue().Set(result);
}
Disclaimer: I'm not a v8 wizard, nor a C++ one, so there may be better ways to do this.
I've written (and use) my own string formatting function and I'd like to simplify the usage of the function, in a specific way shown below, but I'm unsure how.
Here's the relevant code:
// Object that can hold a copy of every type I want to print.
// Stores the copy in a union, with an enumeration to identify
// the type. any uses C++ constructors, but could also be implemented
// with C99 designated initializers, like so: https://ideone.com/ElQgBV
struct any
{
...
}
// The string format function requires the variable arguments
// to all be of the 'any' type for type safety and (essential for
// my purposes) positional printing.
// Arguments are accessed with a va_list, so essentially
// the variable arguments are treated as an array of any objects.
char* format_function_(const char* fmt, ...);
// I call the above function with this macro that expands the
// variable arguments and adds a default-constructed sentinel
// at the end. The sentinel is used by the function to count
// how many arguments were passed.
#define format(fmt, ...) format_function_(fmt, __VA_ARGS__, any())
// Calling the function like so, via the above macro...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
any("world"), any("hello"), any(3.14159f), any(42), any((u8)(1<<4)));
// ...returns this string:
// bits:00010000 string:hello world int:0000002A float:3.14
I'd like to be able to call the function like regular *printf style functions...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
"world", "hello", 3.14159f, 42, (u8)(1<<4));
...with the use of the any object hidden away, possibly behind another macro.
How can I accomplish this?
Edit/Update The positional arguments are essential for my purposes. Any answer that does not preserve this functionality is not a valid answer.
Since the C++11 standard there's something called parameter packs which makes this very simple:
char* format_function(const char* fmt, ...)
{
...
}
template<typename ...T>
char* format(const char* fmt, T... values)
{
return format_function(fmt, any(values)...);
}
...
char* str = format("bits:%4b string:%1 %0 int:%3h float:%2.2\n",
"world", "hello", 3.14159f, 42, (u8)(1<<4));
Maybe you'ld like something like this? (Alert: C++11 code!)
#include <stdio.h>
inline void format() {}
void format(char ch) {
fputc(ch, stdout);
}
void format(int i) {
if(i < 0) {
fputc('-', stdout);
i = -i;
}
int divider = 1;
while(i / divider >= 10)
divider *= 10;
do {
int digit = i / divider;
i -= divider * digit;
divider /= 10;
fputc('0' + digit, stdout);
} while(divider > 0);
}
void format(const char *str) {
fputs(str, stdout);
}
// TODO: Add more 'format()' overloads here!
template<typename FirstArg, typename... OtherArgs>
inline void format(const FirstArg &first, OtherArgs... others) {
format(first);
format(others...);
}
Then, you can simply...
const char *glorifiedIndex(int index) {
switch(index % 10) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
int main(int argc, const char *const argv[]) {
format("Hello, world!\n");
format("My name is ", argv[0], ", and I was given ", argc - 1, " argument", argc != 2 ? "s" : "", ".\n\n");
for(int i = 1; i < argc; i++)
format(i, glorifiedIndex(i), " argument: \"", argv[i], "\"\n");
format("Goodbye, world!\n");
}
This is a more flexible and elegant model, for the following reasons:
Semantically safe.
Type safe.
No <cstdarg> stuff.
No any stuff.
No incredibly badly-designed iostream stuff.
It's too simple to implemet, and I mean too much :). Compare this few lines of code with a typical 3000+ lines long printf.c. The difference is in several orders of magnitude!
You may have nostalgic moments relating with Java and Python.
If you change the type of any expression for whatever reason (i.e, int to unsigned), the function accomodates itself to this.
(Both good and evil) compiler optimizations can kick in easily.
The user of the library may extended the abilities of the format() function by means of overloading it with user-defined types.
This imposibilites the use of dynamic formats (this is intended for obvious security reasons).
This forces you to create special functions for what I call bit-printing, i.e, printing in a machine-parsable way, rather than human-readable as format() did, does, and will do.
You may use overloading features to extend this list yourself :).
There are two pointers to different functions
typedef std::vector<double> TData;
double ( * p_test1 ) ( const TData> &arg);
double ( * p_test2 ) ( const TData> &ar1, char *arg2, char *arg3);
and a method which has as an argument a pointer to the function
double f (double ( * p_test1 ) ( const TData &arg ))
{
//Long and not trivial algorithm processing results of p_test
for ( i = 0;... )
{
double res = p_test (arg); //Some computations
}
}
The f() method contains difficult calculations (here replaced by a for cycle).
Is it possible to templatize this argument (i.e., pointer to a function having different amount of parameters) to get a general function processing both types arguments
double f (double ( * p_test1 ) ( const TData &arg ));
double f (double ( * p_test2 ) ( const TData> &ar1, char *arg2, char *arg3));
Or is there any way how to write such a function, for example to write a pointer to a pointer to the function?
I would like to avoid the partial specialization of f() function because of its complexity (repetitively overwritten of the long code is not efficient).
Thanks for your help...
A method that can take anything can, as a special case, also take function pointer. E.g.
template<typename Function>
double f (Function p_test)
{ ...
// if p_test is a function pointer or has operator(), this will work
double res = p_test (arg);
... }
The problem however gets down to the fact, that the two functions are taking different arguments. So the arguments either have to come somehow bundled to f, there need to be several different implementations anyway, or the arguments will always be the same.
To bundle the arguments, usual method is to use std::bind (C++11) or boost::bind. Say you have a function that needs 3 arguments (test2) and need to pass it to generic algorithm (f) that will only provide the first. And you know the other 2. So you do:
f(bind(&test2, _1, secondarg, thirdarg))
(In C++11 bind is std::bind and _1 is std::placeholders::_1, in Boost bind is boost::bind and _1 is in anonymous namespace provided by the header.) In this case f needs to take any argument, because the return type of bind is unspecified class type with appropriate operator().
You can certainly write a template, at least in C++11:
template <typename ...Args>
double f(double(*fp)(Args...))
{
double res = fp( /* ??? */ );
}
The question is: how do you know how to call the function?