Как использовать тип массива фиксированного размера C в Vala?

Предположим, у меня есть код C (dcomplex.h):

typedef double dcomplex[2];

и хочу использовать такой тип данных в Vala. Каким может быть минимальный vapi-файл и как его вызвать?

(Конечная цель - использовать типы 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 ответ

Решение
  1. public struct DoubleComplexЯ не думаю, что вы можете связываться с массивом C с определением типа и ожидать, что Vala сможет получить доступ к его элементам или полям.

  2. DoubleComplex x = {1.0, 2.0}; это инициализация массивов. Вы не сможете использовать эту инициализацию, так как мы не можем дать Vala знать, что его тип - это "непрозрачный" массив.

Я понимаю, что вы хотите использовать сложные функции C99, поэтому ниже я представляю свое решение для привязки к complex.h, Чтобы сделать сложный заголовок более понятным Vala, я бы не стал писать и VAPI связывать его напрямую, вместо этого я бы написал определение типа стиля на основе обертки C double complex к чему-то, что Вала может связать.

Сначала я покажу обертку, она состоит из трех файлов:

  • Complex.h для прототипов, typedef и включение <complex.h>;
  • Complex.c для реализации функций оболочки и;
  • Complex.vapi связать в Вала.

файл 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
Другие вопросы по тегам