Skip to content

Commit 340535f

Browse files
authored
docs: add more C interop notes and examples (#21965)
1 parent 007f76f commit 340535f

File tree

1 file changed

+99
-1
lines changed

1 file changed

+99
-1
lines changed

doc/docs.md

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7173,6 +7173,104 @@ For all supported options check the latest help:
71737173
71747174
### Calling C from V
71757175
7176+
V currently does not have a parser for C code. That means that even
7177+
though it allows you to `#include` existing C header and source files,
7178+
it will not know anything about the declarations in them. The `#include`
7179+
statement will only appear in the generated C code, to be used by the
7180+
C compiler backend itself.
7181+
7182+
**Example of #include**
7183+
```v oksyntax
7184+
#include <stdio.h>
7185+
```
7186+
After this statement, V will *not* know anything about the functions and
7187+
structs declared in `stdio.h`, but if you try to compile the .v file,
7188+
it will add the include in the generated C code, so that if that header file
7189+
is missing, you will get a C error (you will not in this specific case, if you
7190+
have a proper C compiler setup, since `<stdio.h>` is part of the
7191+
standard C library).
7192+
7193+
To overcome that limitation (that V does not have a C parser), V needs you to
7194+
redeclare the C functions and structs, on the V side, in your `.c.v` files.
7195+
Note that such redeclarations only need to have enough details about the
7196+
functions/structs that you want to use.
7197+
Note also that they *do not have* to be complete, unlike the ones in the .h files.
7198+
7199+
7200+
**C. struct redeclarations**
7201+
For example, if a struct has 3 fields on the C side, but you want to only
7202+
refer to 1 of them, you can declare it like this:
7203+
7204+
**Example of C struct redeclaration**
7205+
```v oksyntax
7206+
struct C.NameOfTheStruct {
7207+
a_field int
7208+
}
7209+
```
7210+
Another feature, that is very frequently needed for C interoperability,
7211+
is the `@[typedef]` attribute. It is used for marking `C.` structs,
7212+
that are defined with `typedef struct SomeName { ..... } TypeName;` in the C headers.
7213+
7214+
For that case, you will have to write something like this in your .c.v file:
7215+
```v oksyntax
7216+
@[typedef]
7217+
pub struct C.TypeName {
7218+
}
7219+
```
7220+
Note that the name of the `C.` struct in V, is the one *after* the `struct SomeName {...}`.
7221+
7222+
**C. function redeclarations**
7223+
The situation is similar for `C.` functions. If you are going to call just 1 function in a
7224+
library, but its .h header declares dozens of them, you will only need to declare that single
7225+
function, for example:
7226+
7227+
**Example of C function redeclaration**
7228+
```v oksyntax
7229+
fn C.name_of_the_C_function(param1 int, const_param2 &char, param3 f32) f64
7230+
```
7231+
... and then later, you will be able to call the same way you would V function:
7232+
```v oksyntax
7233+
f := C.name_of_the_C_function(123, c'here is some C style string', 1.23)
7234+
dump(f)
7235+
```
7236+
7237+
**Example of using a C function from stdio, by redeclaring it on the V side**
7238+
```v
7239+
#include <stdio.h>
7240+
7241+
// int dprintf(int fd, const char *format, ...)
7242+
fn C.dprintf(fd int, const_format &char, ...voidptr) int
7243+
7244+
value := 12345
7245+
x := C.dprintf(0, c'Hello world, value: %d\n', value)
7246+
dump(x)
7247+
```
7248+
7249+
If your C backend compiler is properly setup, you should see something like this, when you try
7250+
to run it:
7251+
```console
7252+
#0 10:42:32 /v/examples> v run a.v
7253+
Hello world, value: 12345
7254+
[a.v:8] x: 26
7255+
#0 10:42:33 /v/examples>
7256+
```
7257+
7258+
Note, that the C function redeclarations look very simillar to the V ones, with some differences:
7259+
1) They lack a body (they are defined on the C side) .
7260+
2) Their names start with `C.` .
7261+
3) Their names can have capital letters (unlike V ones, that are required to use snake_case) .
7262+
7263+
Note also the second parameter `const char *format`, which was redeclared as `const_format &char` .
7264+
The `const_` prefix in that redeclaration may seem arbitrary, but it is important, if you want
7265+
to compile your code with `-cstrict` or thirdparty C static analysis tools. V currently does not
7266+
have another way to express that this parameter is a const (this will probably change in V 1.0).
7267+
7268+
For some C functions, that use variadics (`...`) as parameters, V supports a special syntax for
7269+
the parameters - `...voidptr`, that is not available for ordinary V functions (V's variadics are
7270+
*required* to have the same exact type). Usually those are functions of the printf/scanf family
7271+
i.e for `printf`, `fprintf`, `scanf`, `sscanf`, etc, and other formatting/parsing/logging
7272+
functions.
7273+
71767274
**Example**
71777275
71787276
```v
@@ -7797,4 +7895,4 @@ Assignment Operators
77977895
&= |= ^=
77987896
>>= <<= >>>=
77997897
&&= ||=
7800-
```
7898+
```

0 commit comments

Comments
 (0)