在C中,从函数返回2个变量

时间:2018-07-05 04:14:11

标签: python c python-2.7 return-value ctypes

基本上,我有一个C函数,可以打印出某些数字,并且我还希望该函数返回2个值。我已经使用struct进行了尝试,但是操作不正确,并且不确定如何继续。我已经阅读了其他问题,并且我知道使用指针会更好,但是我不确定该怎么做。

我的C代码如下:

struct re_val
{
    double predict_label;
    double prob_estimates;
    predict_label = 5.0;
    prob_estimates = 8.0;
};

int c_func(const char* dir, double a, double b, double c, double d)
{
    double x[] = { a, b, c, d };

    printf("x[0].index: %d \n", 1);
    printf("x[0].value: %f \n", x[0]);

    printf("x[1].index: %d \n", 2);
    printf("x[1].value: %f \n", x[1]);

    printf("x[2].index: %d \n", 3);
    printf("x[2].value: %f \n", x[2]);

    printf("x[3].index: %d \n", 4);
    printf("x[3].value: %f \n", x[3]);

    return re_val;
}

最终,我只想调用一个能够打印出数组并返回predict_labelprob_estimates的函数。

我实际上是通过ctypes在python中调用此函数的,以下是我的python函数。

calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
calling_function.c_func.restype =  ctypes.c_double
y = calling_function.c_func("hello",1.1, 2.2, 3.1, 4.2)
print y

3 个答案:

答案 0 :(得分:3)

首先,您需要定义结构:

struct re_val{
    float predict_label;
    float prob_estimates;
};

然后您需要从函数中返回一个struct re_val

struct re_val c_func(const char* dir, float a, float b, float c, float d )
{
    /* ... all that stuff ... */

    struct re_val r;
    r.predict_label = 5.0f;
    r.prob_estimates = 8.0f;   
    return r;
}

因此,完整的示例将是:

struct re_val{
    float predict_label;
    float prob_estimates;
};

struct re_val c_func(const char* dir, float a, float b, float c, float d )
{

    /* ... all that stuff ... */

    struct re_val r;
    r.predict_label = 5.0f;
    r.prob_estimates = 8.0f;   
    return r;
}

int main(void)
{
    struct re_val r = c_func("",1.0f,2.0f,3.0f,4.0f);
    printf("predict_label=%.1f\n",r.predict_label);
    printf("predict_label=%.1f\n",r.prob_estimates);
    return 0;
}

在这里尝试:http://rextester.com/WRROW32352

答案 1 :(得分:2)

这通常是通过结构来完成的。要将其初始化在堆栈上,请执行以下操作。

#include <stdio.h>  /* printf */
#include <assert.h> /* assert */

struct sample {
    float x[4];
};

struct re_val {
    float predict_label, prob_estimates;
};

/** Returns the re_val of x. */
static struct re_val c_func(const struct sample *const x) {
    struct re_val rv;
    float a;
    assert(x); /* Debug warn if called with null. */
    rv.predict_label = (x->x[0] + x->x[1]) * 5.0f;
    a = x->x[2] + x->x[3];
    if(a < 0.01f) a = 0.01f;
    rv.prob_estimates = 1.0f / a;
    return rv;
}

/** Prints the re_val. */
static void print(const struct re_val *const rv) {
    assert(rv);
    printf("# prediction label\tprobability estimates\n%g\t%g\n",
        rv->predict_label, rv->prob_estimates);
}

int main(void) {
    const struct sample x = { { 0.1f, 0.2f, 1.0f, 100000.0f } };
    const struct re_val rv = c_func(&x);
    print(&rv);
    return 0;
}

查看此链接Are there any downsides to passing structs by value in C, rather than passing a pointer?;具体来说,原型可能是在static void c_func(const struct sample *const x, struct re_val *const rv);处填充了rv指针的地方,尤其是在re_val是一个大结构或希望将其潜在地分配到堆上的情况下。

有多种方法可以将信息从函数中传递出去,例如,

  • 返回堆栈,如此处所示。通常,这对于内存标记比较琐碎的结构是有利的。 divstrtod64
  • 传递一个指向要填充数据的指针。 freadfscanfsnprintfsprintfstrfmonstrncatstrncpystrptime,{{ 1}},strftimeasctime_rctime_r
  • 保持localtime_r -此方法不会再次进入,并且会多次覆盖相同的数据。它不是线程安全的。 static structasctimectimegmtimelocaltime
  • 具有与需要传递以进行操作的状态相关的类型,strtokFILE * / fopenfcloseregex_t / { {1}}或全局regcompregfree
  • 返回用户必须释放的堆分配指针。例如,errno

答案 2 :(得分:1)

此答案是使用结构的替代方法-这当然是有效的-您可以通过引用/通过指针返回多个值。并回答了主要问题,即是否可以从单个函数返回多个值。

#include<stdio.h>

void sum_diff(double a, double b, double* sum, double*diff)
{
    if (sum) // Only assign when we have a valid reference
        *sum = a + b;
    if (diff)
        *diff= a - b;
}

int main() {

    double diff, sum;
    double a = 4, b = 3;

    sum_diff(a, b, &sum, &diff);

    fprintf(stdout, "The sum of %lf and %lf is %lf\n", a, b, sum);
    fprintf(stdout, "The difference of %lf and %lf is %lf\n", a, b, diff);

    return 0;
}

sum_diff分配的函数使用参数absumdiffab是输入参数,sumdiff是输出参数。请注意,该函数检查sum和diff是否为NULL,这使调用方可以选择获取差值或sum。使用更多的计算密集型计算可能会很方便。