3

假设我有一个 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]);
                                 ^^^^
4

1 回答 1

3
  1. public struct DoubleComplex:我不认为您可以绑定到类型定义的 C 数组并期望 Vala 能够访问其成员或字段。

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

我了解您想使用 C99 复杂功能,因此,我将在下面介绍我的绑定到complex.h. 为了使复杂的标头更适合 Vala,我不会编写 VAPI 来直接绑定它,而是编写一个基于 C 包装器对象的样式 typedefingdouble complex到 Vala 可以绑定的东西。

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

  • Complex.h对于原型,typedef 和包含<complex.h>;
  • 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
于 2017-01-24T15:49:30.430 回答