调用C函数具有可变参数的参数动态 [英] Calling a C function with a varargs argument dynamically

查看:384
本文介绍了调用C函数具有可变参数的参数动态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编程用C对第三方库(惠普/ Mercury LoadRunner的),允许可变参数式可变大小的参数列表它的一个功能。我想调用这个函数,但我不知道前面有多少争论都会有。

有是通过我的供应稍微但这里的问题是,这种函数假定最坏的情况下(3000的参数)和手工codeS为predecessors之一制成的功能

要亮,这里的code中的(开始)。我们调用函数是 web_submit_data()。这将HTTP POST一组表格数据。这种实现是约与动态生成的表单处理场任意数量的时候。
(整理了从原来的,它通过携手codeD索引以及..公平位)


  web_submit_data_buffer_gazillion_items(为const char * BufferName中,为const char * bufferValue)
{
    const int的大小= 129;
    INT I = 0;
    INT J = 11;    web_submit_data(安培; BufferName中[我++ *尺寸],//某种形式的
&安培; BufferName中[我++ *尺寸],//\"Action=https://blah.blah/form);
&安培; BufferName中[我++ *尺寸],//方法= POST);
&安培; BufferName中[我++ *尺寸],//TargetFrame =);
&安培; BufferName中[我++ *尺寸],//RecContentType = text / html的);
&安培; BufferName中[我++ *尺寸],//\"Referer=https://blah.blah/index.html);
&安培; BufferName中[我++ *尺寸],//\"Snapshot=t1.inf);
&安培; BufferName中[我++ *尺寸],//模式= HTML);
的ItemData,//失踪行动:指标8到10
&安培; BufferName中[J *尺寸],和放大器; bufferValue [J ++ *尺寸],ENDITEM,
&安培; BufferName中[J *尺寸],和放大器; bufferValue [J ++ *尺寸],ENDITEM,
&安培; BufferName中[J *尺寸],和放大器; bufferValue [J ++ *尺寸],ENDITEM,
..
(重复上次的3行广告nauseum)
..
&安培; BufferName中[J *尺寸],和放大器; bufferValue [J ++ *尺寸],ENDITEM,
&安培; BufferName中[J *尺寸]);
}

现在我发现,可能工作外部库( http://www.dyncall.org ),但我宁愿不一)完全取决于处理器和b)试图教给外部源链接LoadRunner的。

编辑:
原函数使用而不是使用一个变量硬$ C $光盘索引。仍然可以恢复,如果它原来是太联合国predictable。但是,因为我不可能用不同的编译器或硬件/操作系统运行这个我怀疑这确实​​是值得的。

另外:我没有过web_submit_data实施控制()。因此,只需按下问题下移一级是不会削减它。

另外一点要注意:为 web_submit_data该规范()使用一个名为LAST标记参数列表的末尾不变。最初的实现不使用它。 presumably的调用点确实..


解决方案

可变长度参数基本上只是一个指针传递到所需要的功能一堆填充数据。这就是所谓的功能间preT这打包数据的责任。

该架构安全的方式做到这一点是使用va_list的宏(即正亚历山大提到的),否则你可能会遇到的问题与数据类型如何在各种填充内存

设计的正确方法可变参数的功能是将实际上有两个版本,一个接受的...,而这又提取va_list的,并将其传递给接受的va_list的功能。这种方式可以动态构造的参数,如果你需要,可以改为调用函数的va_list的版本。

大多数标准IO功能具有可变参数版本:vprintf像printf,vsprintf中的sprintf的...你的想法。看看你的库实现了一个名为vweb_submit_data或东西的效果功能。如果他们不这样做,给他们发邮件,告诉他们解决他们的图书馆。

3000行同样的事情(哪怕是preprocessor诱导)令我生厌

I am programming in C against a third party library (in HP/Mercury Loadrunner) that allows a varargs-style variable size argument list for one of it's functions. I want to call this function but I do not know up front how many arguments I will have.

There is a function made by one of my predecessors that serves somewhat but the problem here is that this function assumes the worst case scenario (over 3000 arguments) and hand-codes for that.

To illuminate, here's the (beginning of) the code. The function we call is web_submit_data(). It will HTTP post a set of form data. This implementation came about when dealing with dynamically generated forms with an arbitrary number of fields. (Cleaned up a fair bit from the original, which hand coded indexes by hand as well..)


web_submit_data_buffer_gazillion_items( const char *bufferName, const char *bufferValue)
{
    const int size = 129;
    int i = 0;
    int j = 11;

    web_submit_data(&bufferName[i++ * size], //"some form"
				&bufferName[i++ * size], //"Action=https://blah.blah/form");
				&bufferName[i++ * size], //"Method=POST");
				&bufferName[i++ * size], //"TargetFrame=");
				&bufferName[i++ * size], //"RecContentType=text/html");
				&bufferName[i++ * size], //"Referer=https://blah.blah/index.html");
				&bufferName[i++ * size], //"Snapshot=t1.inf");
				&bufferName[i++ * size], //"Mode=HTML");
				ITEMDATA,  // missing in action: indexes 8 through 10
				&bufferName[j * size],&bufferValue[j++ * size], ENDITEM, 
				&bufferName[j * size],&bufferValue[j++ * size], ENDITEM, 
				&bufferName[j * size],&bufferValue[j++ * size], ENDITEM, 
..
(repeat the last 3 lines ad nauseum)
..
				&bufferName[j * size],&bufferValue[j++ * size], ENDITEM,
				&bufferName[j * size]);  
}

Now I have found an external library that might work (http://www.dyncall.org) but I would much rather not a) be completely processor dependant and b) attempt to teach Loadrunner about linking in external sources..

Edit: The original function used hardcoded indexes instead of using a variable. Can still revert to that if it turns out to be too unpredictable. However, as I am unlikely to run this with a different compiler or hardware / OS I doubt that really is worth it.

Also: I don't have control over the implementation of web_submit_data(). So just pushing the problem down one level isn't going to cut it..

Another thing to note: The spec for web_submit_data() uses a constant called LAST to mark the end of the argument list. The original implementation doesn't use it. Presumably the callsite does ..

解决方案

Variable length arguments are basically just a pointer to a bunch of packed data that is passed to the required function. It is the responsibility of the called function to interpret this packed data.

The architecture safe way to do this is to use the va_list macros (that n-alexander mentioned), otherwise you may run into issues with how various data types are padded in memory.

The proper way to design varargs functions is to actually have two versions, one that accepts the '...', which in turn extracts the va_list and passes it to a function that takes a va_list. This way you can dynamically construct the arguments if you need to and can instead call the va_list version of the function.

Most standard IO functions have varargs versions: vprintf for printf, vsprintf for sprintf... you get the idea. See if your library implements a function named "vweb_submit_data" or something to that effect. If they don't, email them and tell them to fix their library.

3000 lines of the same thing (even if it is preprocessor induced) makes me cringe

这篇关于调用C函数具有可变参数的参数动态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆