Assume I have a C code (dcomplex.h):
typedef double dcomplex[2];
and want to use such a data type in vala. What can be the minimal vapi file and vala call for it?
(The ultimate goal is to use the C99 complex.h types.)
I tried many variants of the following dcomplex.vapi file:
[CCode (cheader_filename = "dcomplex.h")]
namespace DComplex {
[SimpleType]
[CCode (cname = "dcomplex", has_type_id = false)]
public struct DoubleComplex {
}
}
and using in vala code like:
using DComplex;
void main()
{
DoubleComplex x = {1.0, 2.0};
stdout.printf("x = %f + i %f\n", x[0], x[1]);
}
The compilation
valac --vapidir . --pkg dcomplex test.vala
leads to errors:
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]);
^^^^
public struct DoubleComplex
: I don't think you can bind to a typedefed C array and expect Vala to be able to access its members or fields.
DoubleComplex x = {1.0, 2.0};
is a initialization of arrays. You will not be able to use this initialization since we cannot let Vala knows its type is an binded "opaque" array.
I understand you want to use C99 complex features, so, bellow, I present my solution to bind to complex.h
. To make the complex header more Vala fiendly, I'd not write and VAPI to bind it directly, instead I'd write a C wrapper object based style typedefing double complex
to something Vala can bind to.
First I'll show the wrapper, it is composed of three files:
Complex.h
for the prototypes, typedef and inclusion of <complex.h>
;Complex.c
for the implementation of wrapper functions and;Complex.vapi
to bind in Vala.file 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);
file 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);
}
file 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 ();
}
}
Now that you have the wrapper and VAPI, you can use it in Vala code:
file 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());
}
}
To build and run:
# valac Main.vala Complex.vapi Complex.c
# ./Main
The presented example outputs:
C Complex Type = 10.000000 20.000000