如何在 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]);
^^^^
public struct DoubleComplex
:我不认为你可以绑定到类型定义的 C 数组并期望 Vala 能够访问它的成员或字段。
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
假设我有一个 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]);
^^^^
public struct DoubleComplex
:我不认为你可以绑定到类型定义的 C 数组并期望 Vala 能够访问它的成员或字段。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