I have two files, client.vala
and lib.vapi
.
The VAPI defines a class (that would usually talk to C code):
class Toplevel.Sub.CClass
{
public uint i;
}
And client.vala
uses the class:
class Toplevel.Sub.UserClass
{
public Toplevel.Sub.CClass c_class;
}
int main()
{
var cls = new Toplevel.Sub.UserClass();
cls.c_class.i = 0;
return 0;
}
When I attempt to compile the program, I get an error:
$ valac client.vala lib.vapi
/tmp/bug/client.vala.c:7:20: fatal error: client.h: No such file or directory
compilation terminated.
error: cc exited with status 256
Compilation failed: 1 error(s), 0 warning(s)
The compiler seems to want a header generated for the functions in client.vala
.
Is this a bug or am I missing something?
You've discovered something I didn't know about the Vala compiler. client.h
is the default C header name generated by the compiler when no alternative is provided. It has used the basename of the source Vala file. You can change this using the cheader_filename
CCode detail. Change what you have in your VAPI to:
[CCode (cheader_filename = "my_real_c_header.h")]
class Toplevel.Sub.CClass
{
public uint i;
}
and you will see the include is now #include "my_real_c_header.h"
By the way if you compile with valac client.vala --vapididr . --pkg lib
you will see the header is included as #include <my_real_c_header.h>
. Personally I think VAPIs should be used with the --pkg
option.
If you are literally using Toplevel.Sub.CClass
to 'usually talk to C code' then you have misunderstood the purpose of a VAPI. I take 'talk to' to mean calling various C functions and collecting the results so they can be presented in a more Vala friendly way to the rest of your program. So it is a wrapper interface.
A VAPI contains instructions to the Vala compiler to translate names into the right names for the C interface. For example you might have a very simple C function, void top_level_do_something ()
, that you want to use in Vala. In Vala it helps to use a namespace so the VAPI could be:
[CCode (cheader_filename = "my_real_c_header.h")]
namespace TopLevel {
[CCode (cname = "top_level_do_something")]
public void do_something ();
}
You can then call this in Vala with TopLevel.do_something ()
and the compiler would write this out as top_level_do_something ()
in C.
Take a look at Writing a VAPI Manually for more details.