diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 8284f24ddd..cefda5d5d0 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -142,6 +142,12 @@ pub fn (mut ts TestSession) print_messages() { pub fn new_test_session(_vargs string, will_compile bool) TestSession { mut skip_files := []string{} + + // Skip the call_v_from_c files. They need special instructions for compilation. + // Check the README.md for detailed information. + skip_files << 'examples/call_v_from_c/v_test_print.v' + skip_files << 'examples/call_v_from_c/v_test_math.v' + if will_compile { $if msvc { skip_files << 'vlib/v/tests/const_comptime_eval_before_vinit_test.v' // _constructor used diff --git a/doc/docs.md b/doc/docs.md index 75fdec27f7..e3d5e88434 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -115,6 +115,7 @@ To do so, run the command `v up`. * [sizeof and __offsetof](#sizeof-and-__offsetof) * [Calling C from V](#calling-c-from-v) * [Calling V from C](#calling-v-from-c) + * [Export to shared library](#export-to-shared-library) * [Atomics](#atomics) * [Global Variables](#global-variables) * [Debugging](#debugging) @@ -5007,7 +5008,13 @@ fn main() { ## Calling V from C -Since V can compile to C, calling V code from C is very easy. +Since V can compile to C, calling V code from C is very easy, once you know how. + +Use `v -o file.c your_file.v` to generate a C file, corresponding to the V code. + +More details in [call_v_from_c example](../examples/call_v_from_c). + +## Export to shared library By default all V functions have the following naming scheme in C: `[module name]__[fn_name]`. diff --git a/examples/call_v_from_c/.gitignore b/examples/call_v_from_c/.gitignore new file mode 100644 index 0000000000..20bd2351e6 --- /dev/null +++ b/examples/call_v_from_c/.gitignore @@ -0,0 +1,2 @@ +# Ignore the generated C files in this directory +*.c diff --git a/examples/call_v_from_c/README.md b/examples/call_v_from_c/README.md new file mode 100644 index 0000000000..f4f58471c1 --- /dev/null +++ b/examples/call_v_from_c/README.md @@ -0,0 +1,39 @@ +## A simple example to show how to call a function written in v from c + +### Compile as a shared library + +#### On Linux: + +Step 1: Compile the v code to a shared library using `v -cc gcc -shared v_test_print.v` or +`v -cc gcc -shared v_test_math.v`. + +Step 2: Compile the c file using `gcc test_print.c v_test_print.so -o test_print` or +`gcc test_math.c v_test_math.so -o test_math`. + +Step 3: Run the compiled c file using `LD_LIBRARY_PATH=. ./test_print` or +`LD_LIBRARY_PATH=. ./test_math`. + +#### On Windows: + +Step 1: Compile the v code to a shared library using `v -cc gcc -shared v_test_print.v` or +`v -cc gcc -shared v_test_math.v`. + +Step 2: Compile the c file using `gcc test_print.c v_test_print.dll -o test_print.exe` or +`gcc test_math.c v_test_math.dll -o test_math.exe`. + +Step 3: Run the compiled c file using `test_print.exe` or `test_math.exe`. + +### Compile as a c file + +***Requirements: `libgc` must be installed*** + +Step 1: Compile the v code to a shared library using +`v -shared -cc gcc -o v_test_print.c v_test_print.v` or +`v -shared -cc gcc -o v_test_math.c v_test_math.v`. + +*Specifying the output with a `.c` extension will generate the corresponding C source file.* + +Step 2: Compile the c file using `gcc test_print.c v_test_print.c -o test_print -lgc` or +`gcc test_math.c v_test_math.c -o test_math -lgc -lm`. + +Step 3: Run the compiled c file using `./test_print` or `./test_math`. diff --git a/examples/call_v_from_c/test_math.c b/examples/call_v_from_c/test_math.c new file mode 100644 index 0000000000..9b4c619589 --- /dev/null +++ b/examples/call_v_from_c/test_math.c @@ -0,0 +1,14 @@ +#include + +extern int square(int i); + +extern double sqrt_of_sum_of_squares(double x, double y); + +int main() +{ + int i = 10; + printf("square(%d) = %d\n", i, square(i)); + double x=0.9; + double y=1.2; + printf("sqrt_of_sum_of_squares(%f, %f) = %f\n", x, y, sqrt_of_sum_of_squares(x, y)); +} diff --git a/examples/call_v_from_c/test_print.c b/examples/call_v_from_c/test_print.c new file mode 100644 index 0000000000..30e3269963 --- /dev/null +++ b/examples/call_v_from_c/test_print.c @@ -0,0 +1,7 @@ +extern void foo(const char* s); + +int main() +{ + foo("hello"); + foo("bye"); +} diff --git a/examples/call_v_from_c/v_test_math.v b/examples/call_v_from_c/v_test_math.v new file mode 100644 index 0000000000..35373d398b --- /dev/null +++ b/examples/call_v_from_c/v_test_math.v @@ -0,0 +1,13 @@ +module test_math + +import math + +[export: 'square'] +fn calculate_square(i int) int { + return i * i +} + +[export: 'sqrt_of_sum_of_squares'] +fn calculate_sqrt_of_sum_of_squares(x f64, y f64) f64 { + return math.sqrt(x * x + y * y) +} diff --git a/examples/call_v_from_c/v_test_print.v b/examples/call_v_from_c/v_test_print.v new file mode 100644 index 0000000000..fcde1f4b0d --- /dev/null +++ b/examples/call_v_from_c/v_test_print.v @@ -0,0 +1,6 @@ +module test_print + +[export: 'foo'] +fn show_foo(s &char) { + println(unsafe { cstring_to_vstring(s) }) +}