如何在 vala 中使用固定大小的 C 数组类型?

How to use a fixed size C array type in vala?

假设我有一个 C 代码 (dcomplex.h):

typedef double dcomplex[2];

想在vala中使用这样的数据类型。 最小的 vapi 文件和 vala 调用是多少?

(最终目标是使用 C99 complex.h 类型。)

我尝试了以下 dcomplex.vapi 文件的多种变体:

[CCode (cheader_filename = "dcomplex.h")]
namespace DComplex {
   [SimpleType]
   [CCode (cname = "dcomplex", has_type_id = false)]
   public struct DoubleComplex {
   }
}

并在 vala 代码中使用:

using DComplex;
void main()
{  
   DoubleComplex x = {1.0, 2.0};
   stdout.printf("x = %f + i %f\n", x[0], x[1]);
}

编译

valac --vapidir . --pkg dcomplex test.vala

导致错误:

error: too many expressions in initializer list for `Complex.DoubleComplex'
DoubleComplex x = {1.0, 2.0};
                   ^^^

error: The expression `Complex.DoubleComplex' does not denote an array
stdout.printf("x = %f + i %f\n", x[0], x[1]);
                                 ^^^^
  1. public struct DoubleComplex:我不认为你可以绑定到类型定义的 C 数组并期望 Vala 能够访问它的成员或字段。

  2. DoubleComplex x = {1.0, 2.0};是数组的初始化。你将无法使用这个初始化,因为我们不能让 Vala 知道它的类型是一个绑定的 "opaque" 数组。

我知道您想使用 C99 的复杂功能,所以,下面,我将展示我的绑定到 complex.h 的解决方案。为了使复杂的 header 更像 Vala,我不会编写 VAPI 来直接绑定它,而是编写一个基于 C 包装器 object 的样式类型定义 double complex 到 Vala 可以绑定到。

首先我会展示包装器,它由三个文件组成:

  • Complex.h 用于 <complex.h>;
  • 的原型、typedef 和包含
  • Complex.c用于包装函数的实现;
  • Complex.vapi 在 Vala 中绑定。

文件Complex.h

#include <complex.h>

typedef double complex dcomplex;

void dcomplex_make (dcomplex * c, double r, double i);

double dcomplex_real (dcomplex * c);
double dcomplex_imag (dcomplex * c);

文件Complex.c

#include "Complex.h"

void dcomplex_make (dcomplex * c, double r, double i)
{
    *c = CMPLX(r, i);
}

double dcomplex_real (dcomplex * c)
{
    return creal(*c);
}

double dcomplex_imag (dcomplex * c)
{
    return cimag(*c);
}

文件Complex.vapi

[CCode (cheader_filename = "Complex.h")]
namespace Complex
{
    [CCode (cname = "dcomplex")]
    public struct DComplex {
        [CCode (cname = "dcomplex_make")]
        public DComplex (double real, double imaginary);

        [CCode (cname = "dcomplex_real")]
        public double real ();

        [CCode (cname = "dcomplex_imag")]
        public double imag ();
    }
}

现在您已经有了包装器和 VAPI,您可以在 Vala 代码中使用它了:

文件Main.vala

using Complex;

class Main {
    static void main() {
        DComplex c = DComplex(10, 20);

        stdout.printf("C Complex Type = %f %f\n", c.real(), c.imag());
    }
}

构建和运行:

# valac Main.vala Complex.vapi Complex.c
# ./Main

给出的示例输出:

C Complex Type = 10.000000 20.000000