C 具有可变输入的函数指针
在C语言中,我试图将一个单变量函数传递给一个优化例程(C 具有可变输入的函数指针,c,function-pointers,C,Function Pointers,在C语言中,我试图将一个单变量函数传递给一个优化例程(optimization\u routine)。优化例程将指向单个float变量函数的指针func1ptr作为输入。但是,我需要能够将多个变量传递到此函数中。因此,我试图构造一个变量的函数指针,其中除第一个输入外,所有输入都是函数变量的“常量”(类似于微积分中的偏导数)。我想我可以用函数指针来实现这一点,但我想不出有意义的语法 也就是说,我有这样一个函数: float function_all_inputs( float A, int B,
optimization\u routine
)。优化例程将指向单个float
变量函数的指针func1ptr
作为输入。但是,我需要能够将多个变量传递到此函数中。因此,我试图构造一个变量的函数指针,其中除第一个输入外,所有输入都是函数变量的“常量”(类似于微积分中的偏导数)。我想我可以用函数指针来实现这一点,但我想不出有意义的语法
也就是说,我有这样一个函数:
float function_all_inputs( float A, int B, float C, char D);
typedef (*func1ptr)(float);
void optimization_function( func1ptr fp );
优化函数需要如下指针:
float function_all_inputs( float A, int B, float C, char D);
typedef (*func1ptr)(float);
void optimization_function( func1ptr fp );
因此,我想构造一个这种形式的函数:
// create a function of A only at runtime using inputs B,C,D
func1ptr fp = ( & function_all_inputs(A,B,C,D))(A);
fp
指向的函数应具有以下签名:
float function_one_input(float A);
输入B、C和D在代码的其他地方计算,因此在编译时是未知的;但是,它们在优化函数中是常量
我想我可以在纯C中使用函数指针来实现这一点,但是,我无法找出正确的语法。我在网上找到的例子都没有涉及到这个案例。如果您能提供任何建议,我们将不胜感激。听起来您好像在问如何在C中捕获参数,您可以查看链接问题中的一些选项
但是,如果没有自定义扩展,我认为您需要使用全局变量来实现所需的效果
// Pass this wrapper with the name "wrapper" into the function
// that requires a function pointer
void wrapper(float a) {
// Where last four arguments are global variables that are computed first.
function_all_inputs(a, b, c, d, e);
}
// No need to create an explicit function pointer.
// Passing the name of the function is sufficient.
optimization_function(wrapper);
您需要编写一个包装函数,如
int b;
float c;
char d;
int wrap(float a) {
return function_all_inputs(a, b, c, d);
}
将并发视为重新进入:
如果多个线程可以使用包装器,并且需要它传递不同的数据,请将这些全局线程设置为本地:
_Thread_local int b;
如果您需要完全重新进入,事情会变得复杂:
在使用具有不同参数的嵌套调用之前,还需要保存变量。
使用不同的global编写第二个(也许是第三个)版本的包装器可能更好
如果您同时需要更多的活动,您可以尝试使用这些函数,尽管它很快就会变得非常笨拙。最好通过添加一个上下文参数来更改优化函数,并将这些额外的参数一起传递
为了完全自由,您确实需要一种在运行时编写函数的方法,至少足以恢复上下文指针。但是,在纯C中这是不可能的。如果在您的平台上sizeof(float)>=sizeof(void*)
,那么您可以按如下方式“破解”它:
typedef struct
{
float a;
int b;
float c;
char d;
}
params;
int function_all_inputs(float a, int b, float c, char d)
{
...
}
int function_one_input(float f)
{
params* p;
memcpy((void*)&p, (void*)&f, sizeof(void*));
return function_all_inputs(p->a, p->b, p->c, p->d);
}
int optimize()
{
float f;
params v;
params* p = &v;
v.a = ...;
v.b = ...;
v.c = ...;
v.d = ...;
memcpy((void*)&f, (void*)&p, sizeof(void*));
return optimization_function(function_one_input, f);
}
您在关于返回值类型的问题上不是很一致,因此我使用了int
这可能有些过分,但支持以以下方式创建闭包:
#include <stdio.h>
#include <ffi.h>
typedef struct BCD { int B; float C; char D; } BCD;
void function_one_input_binding
(ffi_cif* cif, int* result, void** args, BCD* bcd) {
*result = function_all_inputs(*(float*)args[0], bcd->B, bcd->C, bcd->D);
}
int main() {
ffi_cif cif;
ffi_type* args[1];
ffi_closure* closure;
int (*function_one_input)(float);
// Allocate a closure.
closure = ffi_closure_alloc(sizeof(ffi_closure), &function_one_input);
// Tell libffi the parameter and return types.
args[0] = &ffi_type_float;
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_int, args);
// Bind closure data.
BCD bcd = { .B = 1, .C = 2.5, .D = 'x' };
ffi_prep_closure_loc(
closure, &cif, function_one_input_binding, &bcd, function_one_input);
// Call the function.
int result = function_one_input(42.5);
// Free the allocated closure.
ffi_closure_free(closure);
return 0;
}
#包括
#包括
typedef结构BCD{int B;float C;char D;}BCD;
无效函数\u一个\u输入\u绑定
(ffi_cif*cif,int*结果,无效**参数,BCD*BCD){
*结果=函数所有输入(*(浮点*)参数[0],bcd->B,bcd->C,bcd->D);
}
int main(){
外国金融机构到岸价;
ffi_类型*参数[1];
外国金融机构关闭*关闭;
int(*函数一输入)(浮点);
//分配一个闭包。
闭包=ffi\u闭包\u分配(sizeof(ffi\u闭包)和函数\u一个\u输入);
//告诉libffi参数和返回类型。
args[0]=&ffi\u type\u float;
ffi_prep_cif(&cif,ffi_DEFAULT_ABI,1,&ffi_type_int,args);
//绑定闭包数据。
BCD BCD={.B=1.C=2.5.D='x'};
外国金融机构准备结束地点(
闭包、&cif、函数\输入\绑定、&bcd、函数\输入);
//调用函数。
int结果=功能一输入(42.5);
//释放分配的闭包。
外国金融机构自由关闭(关闭);
返回0;
}
Hmm,谢谢你的建议。“结束”这个词是我一直在寻找的——我已经见过很多次了,但不知道它是什么意思。如果可能的话,我希望避免使用全局变量,因为我计划将其放入DLL中。@user1004061,不幸的是,C本机不支持闭包。我认为C++的更新标准是这样的,所以你可能想考虑。@ USS1004061,一种减少命名空间污染的方法是使用<代码>静态< /Cord>关键字至少使全局变量在当前编译单元中可见。@ MelLun2011:是的,新的C++标准支持闭包,称为“lambda”。尽管它们只有在纯函数(无数据)的情况下才可转换为函数指针。因此,没有优势。@重复数据消除还是有优势的,因为如果您从函数指针切换到函数对象(ah lastd::function
),您可以将lambda表达式与数据一起传递。谢谢您的建议。虽然我没有显式地为多线程编码,但我清楚地看到这可能是一个问题。我知道在运行时编写函数是不可能的。我习惯于解释性语言,所以我仍然习惯于C:)中的这些限制。optimization\u function()
是同步调用传入的函数,还是将其隐藏在某个地方,稍后再调用?如果您多次调用optimization\u function()
,它是想记住您传入的每个函数,还是只记住最后一个函数?我不完全理解您的问题,但这可能会有所帮助:optimization\u function
多次调用fp
指向的函数。每次optimization\u function
调用fp
,它的值都不同。如果传递给optimization\u function()
的函数中有一个打印函数,您会看到打印输出在optimization\u function()返回之前出现吗,或者稍后您会看到打印输出吗?是的,您会在'optimization_function()`返回之前看到打印语句(实际上,您会看到它多次,因为optimization_function
多次调用fp
函数)。我已经证实了这一点。似乎不可能用纯C来实现一个curry函数。