docs,tests: add project_with_c_code_2 (passing structs from C to V to C)
parent
0e55534c6e
commit
5c93f942be
|
@ -2413,6 +2413,8 @@ and tries to compile it to a .o file, then will use that.
|
|||
This allows you to have C code, that is contained in a V module, so that its distribution is easier.
|
||||
You can see a complete minimal example for using C code in a V wrapper module here:
|
||||
[project_with_c_code](https://github.com/vlang/v/tree/master/vlib/v/tests/project_with_c_code).
|
||||
Another example, demonstrating passing structs from C to V and back again:
|
||||
[interoperate between C to V to C](https://github.com/vlang/v/tree/master/vlib/v/tests/project_with_c_code_2).
|
||||
|
||||
You can use `-cflags` to pass custom flags to the backend C compiler. You can also use `-cc` to change the default C backend compiler.
|
||||
For example: `-cc gcc-9 -cflags -fsanitize=thread`.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
main
|
||||
main_test
|
||||
modc/impl.o
|
||||
modc/impl.obj
|
|
@ -0,0 +1,5 @@
|
|||
Do not delete this file.
|
||||
|
||||
It is used by V to stop the lookup for v.mod,
|
||||
so that the top level vlib/v.mod is not found,
|
||||
if you delete modc/v.mod .
|
|
@ -0,0 +1,14 @@
|
|||
module main
|
||||
|
||||
import modc
|
||||
|
||||
// passing array of Vtype to C
|
||||
// Vtype wraps a C type
|
||||
fn main() {
|
||||
a := [1, 2, 3, 4]
|
||||
mut vals := []modc.Vtype{}
|
||||
for v in a {
|
||||
vals << modc.new_vtype(v)
|
||||
}
|
||||
modc.call_with_array_param(vals)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import modc
|
||||
|
||||
fn test_using_c_code_in_the_same_module_works() {
|
||||
x := modc.new_vtype(123)
|
||||
modc.destroy_vtype(x)
|
||||
assert true
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef CMOD_H
|
||||
#define CMOD_H
|
||||
|
||||
struct Atype {
|
||||
int val;
|
||||
};
|
||||
|
||||
|
||||
void* new_atype(int n);
|
||||
|
||||
void handle_array(void *p, int n);
|
||||
|
||||
void handle_array2(void *p, int n);
|
||||
|
||||
void destroy_atype(void *p);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include "header.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void* new_atype(int n) {
|
||||
struct Atype *x = malloc(sizeof(struct Atype));
|
||||
x->val = n;
|
||||
return x;
|
||||
}
|
||||
|
||||
// pointer to first element of array
|
||||
void handle_array(void *p, int n) {
|
||||
struct Atype *ptr = (struct Atype *)p;
|
||||
for (int i=0; i<n; i++) {
|
||||
printf("%d - %d\n", i, ptr[i].val);
|
||||
}
|
||||
}
|
||||
|
||||
// pointer to array
|
||||
void handle_array2(void *p, int n) {
|
||||
struct Atype (*ptr)[];
|
||||
ptr = p;
|
||||
for (int i=0; i<n; i++) {
|
||||
printf("%d - %d\n", i, (*ptr+i)->val);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_atype(void *p) {
|
||||
free(p);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Module {
|
||||
name: 'modc',
|
||||
description: 'Another module, wrapping some C code.',
|
||||
dependencies: []
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
module modc
|
||||
|
||||
#flag -I @VROOT
|
||||
#flag @VROOT/impl.o
|
||||
#include "header.h"
|
||||
struct C.Atype {
|
||||
}
|
||||
|
||||
// NB: [trusted] below, means that the C function, can be safely called outside unsafe{} blocks.
|
||||
//
|
||||
// By default, all C. functions are NOT trusted, and all V functions are by default trusted.
|
||||
//
|
||||
// Relatedly, if you want to mark a V function as unsafe, use [unsafe].
|
||||
//
|
||||
// The V compiler forces all calls of unsafe functions to be wrapped in `unsafe{...}` blocks.
|
||||
struct Vtype {
|
||||
pub mut:
|
||||
p &C.Atype
|
||||
}
|
||||
|
||||
fn C.new_atype(int) voidptr
|
||||
|
||||
[trusted]
|
||||
fn C.handle_array(voidptr, int)
|
||||
|
||||
fn todo_remove_me() {
|
||||
// TODO: remove this dummy function, when the vfmt bug of [trusted] after a void C function is fixed
|
||||
}
|
||||
|
||||
[trusted]
|
||||
fn C.handle_array2(voidptr, int)
|
||||
|
||||
fn C.destroy_atype(voidptr)
|
||||
|
||||
pub fn new_vtype(n int) Vtype {
|
||||
t := C.new_atype(n)
|
||||
return Vtype{t}
|
||||
}
|
||||
|
||||
pub fn call_with_array_param(arr []Vtype) {
|
||||
mut carr := []C.Atype{}
|
||||
for t in arr {
|
||||
carr << *t.p
|
||||
}
|
||||
// make it safe
|
||||
a := carr
|
||||
C.handle_array(a.data, a.len)
|
||||
C.handle_array2(a.data, a.len)
|
||||
}
|
||||
|
||||
pub fn destroy_vtype(t Vtype) {
|
||||
C.destroy_atype(t.p)
|
||||
}
|
Loading…
Reference in New Issue