Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 具有可变输入的函数指针_C_Function Pointers - Fatal编程技术网

C 具有可变输入的函数指针

C 具有可变输入的函数指针,c,function-pointers,C,Function Pointers,在C语言中,我试图将一个单变量函数传递给一个优化例程(optimization\u routine)。优化例程将指向单个float变量函数的指针func1ptr作为输入。但是,我需要能够将多个变量传递到此函数中。因此,我试图构造一个变量的函数指针,其中除第一个输入外,所有输入都是函数变量的“常量”(类似于微积分中的偏导数)。我想我可以用函数指针来实现这一点,但我想不出有意义的语法 也就是说,我有这样一个函数: float function_all_inputs( float A, int B,

在C语言中,我试图将一个单变量函数传递给一个优化例程(
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 la
std::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函数。