2

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?

Albert Tomanek
  • 387
  • 4
  • 13
  • What are you trying to achieve with that vapi file? Is there an additional C library that you would like to access from Vala code? A Vapi file only serves as a placeholder for `valac` to read and is not useful to the C compiler as it is not translated to C code. Thus, the C compiler does not know about `class Toplevel.Sub.CClass`. So you should also supply the C header that comes with that library to the compiler by, for example, putting it into your build directory. –  May 18 '18 at 16:56

1 Answers1

3

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.

AlThomas
  • 4,169
  • 12
  • 22
  • Thank you @AIThomas -- I modified my code to _actually call_ a C function, and after getting the same error, specifying the `cheader_filename` did the trick. For anyone else facing the same problem, the now working code is [here](http://s000.tinyupload.com/index.php?file_id=50505437598368551388). – Albert Tomanek May 18 '18 at 20:12