I wish to call OCaml code through C++ by compiling OCaml to a static or shared library that contains a C interface. This page seems to explain how to create a C interface for OCaml. But how do I do it and compile it? And how do I obtain the .h file to load in my C++ code?
Also, could someone explain to be this part:
The OCaml runtime system comprises three main parts: the bytecode
interpreter, the memory manager, and a set of C functions that
implement the primitive operations. Some bytecode instructions are
provided to call these C functions, designated by their offset in a
table of functions (the table of primitives).
I thougth OCaml could be compiled to native machine language. Why it is compiled to bytecode and interpreted at runtime? Is it always like that, or only for OCaml libraries compiled with C interface?
Most of that page describes how to call C from OCaml. You want to do the reverse, which is described in Advanced Topics: callbacks from C to OCaml, closer to the bottom of the page.
When you do native compilation there is no bytecode involved, just as you say. The native compiler (ocamlopt) produces ordinary object (.o in Unix) files and extra files containing OCaml metadata.
If you look at Advanced Example with callbacks, you'll see an example where the main program is in C, with calls to two functions defined in OCaml. Things should work similarly in C++. (I have only done this in C myself, however.)
Update
Here is the worked-out example using the code from Advanced example with callbacks. I am running this code on Ubuntu 18.04.4 (x86_64).
The OCaml code looks like this:
$ cat mod.ml
let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 1)
let format_result n = Printf.sprintf "Result is: %d\n" n
let () = Callback.register "fib" fib
let () = Callback.register "format_result" format_result
Compile this code and ask for a complete object file:
$ ocamlopt -output-obj -o bigmod.o mod.ml
Rename the C code to modwrap.cc. (The code is given in the OCaml manual section.)
$ head -6 modwrap.cc
#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
int fib(int n)
Note that the OCaml include files are conditionalized as to whether they're being included from C or C++ (as are almost all header files these days).
The main function from the OCaml manual section is also valid C++; rename it to main.cc:
$ head -7 main.cc
#include <stdio.h>
#include <caml/callback.h>
extern int fib(int n);
extern char * format_result(int n);
int main(int argc, char ** argv)
Now compile and link everything:
$ g++ -c modwrap.cc
$ g++ -o myprog -I $(ocamlopt -where) \
main.cc modwrap.o bigmod.o $(ocamlopt -where)/libasmrun.a -ldl
$
Now run the program
$ ./myprog
fib(10) = Result is: 89
There is no automatic generation of header files. In this example the extern lines of main.cc are the header file in essence. If you want a header file you'll have to write something like this yourself.
Update 2
Here are the commands for creating an actual static library containing the OCaml functions and their wrappers. This assumes that you have done the compiles above to create bigmod.o and modwrap.o:
$ cp $(ocamlopt -where)/libasmrun.a libmyoc.a
$ ar r libmyoc.a bigmod.o modwrap.o
Now you can use this library in your C++ code (represented by main.cc):
$ g++ -o myprog -I $(ocamlopt -where) main.cc -L . -lmyoc -ldl
$ ./myprog
fib(10) = Result is: 89
Update 3
(I updated the above commands to work on Unbuntu.)
Related
I would like to use a library written in D for a C program compilable with MinGW GCC, for Windows. Here are the codes:
dll.d
extern (C) int dsquare(int n) nothrow
{
return n * n;
}
main.c
#include <stdio.h>
int main()
{
int res = dsquare(6); // Expect '36'
printf("res = %d\n", res);
return 0;
}
There is a tutorial on D's site, but it seems to target only Linux. Indeed, no explanation is given for creating such a dynamic D library for Windows and MinGW users.
D's documentation also says that the -shared option should generate a DLL version of the D code, but in my case, it generates an executable, I don't know why.
Also, anything that seems to generate files to be linked targets MVSC formats and nothing seems to be suitable for MinGW GCC compilers.
So, how can I generate a "GCC-friend" DLL with D, so that I can link it to my C program without having to use another compiler, such as GDC or LDC, via gcc main.c -o main -ldll -L. (I guess)?
I attached link with short explanation. Link D onto C is not so straightforward as C to D. Check D.org page here:
https://dlang.org/spec/betterc.html
For my program I am linking 3 files in total. A main.c, sortfile.c and my.h(header file). For my sortfile.c I am implementing a OddEven Sort. I am unsure whether my coding algorithm is correct. Also would like to know what information usually goes in a header file. Is it only the other two c files vide #include?
#include <stdio.h>
void swap(int *, int *);
void Odd_Even_Sort(int *);
/* swaps the elements */
void swap(int * x, int * y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
/* sorts the array using oddeven algorithm */
void Odd_Even_Sort(int * x)
{
int sort = 0, i;
while (!sort)
{
sort = 1;
for (i = 1;i < MAX;i += 2)
{
if (x[i] > x[i+1])
{
swap(&x[i], &x[i+1]);
sort = 0;
}
}
for (i = 0;i < MAX - 1;i += 2)
{
if (x[i] > x[i + 1])
{
swap(&x[i], &x[i + 1]);
sort = 0;
}
}
}
I did not include a main in the sortfile.c because I intended to put main in the main.c file.
You look confused. Read first the wikipage on linkers and on compilers. You don't link source files, but only object files and libraries.
(I am guessing and supposing and hoping for you that you are using Linux)
You also compile translation units into object files.
Header files are for the preprocessor (the first "phase" of the compilation). The preprocessing is a textual operation. See this answer for some hint.
So you probably want to compile your main.c into main.o with
gcc -Wall -g -c main.c -o main.o
(the -Wall asks for all warnings, so never forget that; the -g asks for debugging information; -c asks to compile some source into some object file; order of program arguments to gcc matters a big lot).
Likewise, you want to compile your sortfile.c into sortfile.o. I leave as an exercise to get the right command doing that.
Finally, you want to get an executable program myprogsort, by linking both object files. Do that with
gcc -g main.o sortfile.o -o myprogsort
But you really want to use some build automation tool. Learn about GNU make. Write your Makefile (beware, tabs are important in it). See this example. Don't forget to try make -p to understand (and take advantage of) all the builtin rules make is knowing.
Also would like to know what information usually goes in a header file.
Conventionally you want only declarations in your common header file (which you would #include in every source file composing a translation unit). You can also add definitions of static inline functions. Read more about inline functions (you probably don't need them at first).
Don't forget to learn how to use the gdb debugger. You probably will run
gdb ./myprogsort
more than once. Don't forget to rebuild your thing after changes to source code.
Look also inside the source code of some medium sized free software project coded in C on github. You'll learn a big lot.
I'm trying to learn how to call routines in C directly from OCaml code, using the Ctypes library.
I have this basic example with two files: hello.ml and hello.c.
hello.ml looks like this:
open Ctypes
open Foreign
let hello =
foreign "hello" (float # -> returning void)
;;
let () =
hello 3.15
;;
hello.c looks like this:
#include <stdio.h>
void hello(double x)
{
if ( x > 0)
printf("hello!\n");
}
How do I compile these two files into one executable?
The process of manually compiling/linking code is scary to me and I don't understand it very well. I usually use a Makefile template to compile my code because that's really easy.
Here's an example that I use on OS X.
in simple.c
int adder(int a, int b)
{
return a + b;
}
and in simple.ml
open Ctypes
open Foreign
let adder_ = foreign
"adder" (int #-> int #-> returning int)
let () =
print_endline (string_of_int (adder_ 1 2))
Then I do
clang -shared simple.c -o simple.so
ocamlfind ocamlopt -package ctypes.foreign -cclib simple.so -linkpkg simple.ml -o Test
./Test
And that should print out 3 on the terminal.
I have the following files:
C file with functions:
// funcs.c
#include <stdio.h>
void something() {
printf("something\n");
sayHello();
}
System verilog file:
// hello_world.v
module kuku;
export "DPI-C" function sayHello;
import "DPI-C" function void something();
initial something();
function int sayHello ();
$display("hello world");
sayHello = 1;
endfunction
endmodule
How can I compile it and make this work so when I call something() from SV, it will call the C function, and when I call sayHello() from C, it will call the SV function?
Answering myself:
When SV code is compiled using VCS, it is first translated into C code.
When exporting a function out of SV, it generates a C header file vc_hdrs.h that should be included by the C file.
So a change I made in the C file is to add the line:
#include "vc_hdrs.h"
Then, I just added the C functions file to the VCS compilation command:
> vcs -sverilog hello_world.v funcs.c
It works!
The output I get is:
something
hello world
.
A solution that works with all simulator that follow IEEE Std 1800-2012 is to have #include "svdpi.h" and prefix the extern keyword in front of all methods being exported to C. funcs.c should look like:
#include <stdio.h>
#include "svdpi.h"
extern int sayHello();
void something() {
printf("something\n");
sayHello();
}
Examples from IEEE Std 1800-2012
§ H.10.2 Example 2—Simple packed array application
§ H.10.3 Example 3—Application with complex mix of types
I see you've named SystemVerilog file as .v extension. Not sure if that works or not. But lets say if its hello_world.sv
Your command line should look like this (for Questa Simulator),
qverilog hello_world.sv funcs.c
"qverilog " is to compile and run SystemVerilog files.
That's all. No need to add extra header files
Hi I have provided a nice example under this post
https://stackoverflow.com/a/46441794/5842403
Synopsys VCS
1) You compile the C code using flags and introducing the defines you want to add.
In our case our C code need the define PYTHON_PATH
#GCC in two steps for shared object
gcc -g -D 'PYTHON_PATH="'$PYTHON_DIR'"' -fPIC -Wall -I${VCS_HOME}/include -I/usr/include/python2.6/ -lpython2.6 -c ${PROJECTDIR}/verification/PVE/keycontrol/tb/keycontrol_C_code_wrapper.c
gcc -fPIC -shared -o keycontrol_C_code_wrapper.so keycontrol_C_code_wrapper.o
2) You do the VCS elaboration linking the python lybrary with -LDFLAGS '-lpython2.6'
vcs -timescale=1ps/1ps -ntb_opts uvm -lca -kdb -full64 keycontrol_tb_top -debug_access+all+reverse -LDFLAGS '-lpython2.6'
3) You run the created simulation file. You call simv including -sv_lib keycontrol_C_code_wrapper to import the C shared object.
#RUN C CODE
./simv -gui -ucli +DVE +UVM_NO_RELNOTES -l simv.log +UVM_TESTNAME=keycontrol_basic_test -do ../../verification/PVE/keycontrol/tools/keycontrol_ucli_init.synopsys -sv_lib keycontrol_C_code_wrapper
I am trying to embed binary blobs into an exe file. I am using mingw gcc.
I make the object file like this:
ld -r -b binary -o binary.o input.txt
I then look objdump output to get the symbols:
objdump -x binary.o
And it gives symbols named:
_binary_input_txt_start
_binary_input_txt_end
_binary_input_txt_size
I then try and access them in my C program:
#include <stdlib.h>
#include <stdio.h>
extern char _binary_input_txt_start[];
int main (int argc, char *argv[])
{
char *p;
p = _binary_input_txt_start;
return 0;
}
Then I compile like this:
gcc -o test.exe test.c binary.o
But I always get:
undefined reference to _binary_input_txt_start
Does anyone know what I am doing wrong?
In your C program remove the leading underscore:
#include <stdlib.h>
#include <stdio.h>
extern char binary_input_txt_start[];
int main (int argc, char *argv[])
{
char *p;
p = binary_input_txt_start;
return 0;
}
C compilers often (always?) seem to prepend an underscore to extern names. I'm not entirely sure why that is - I assume that there's some truth to this wikipedia article's claim that
It was common practice for C compilers to prepend a leading underscore to all external scope program identifiers to avert clashes with contributions from runtime language support
But it strikes me that if underscores were prepended to all externs, then you're not really partitioning the namespace very much. Anyway, that's a question for another day, and the fact is that the underscores do get added.
From ld man page:
--leading-underscore
--no-leading-underscore
For most targets default symbol-prefix is an underscore and is defined in target's description. By this option it is possible to disable/enable the default underscore symbol-prefix.
so
ld -r -b binary -o binary.o input.txt --leading-underscore
should be solution.
I tested it in Linux (Ubuntu 10.10).
Resouce file:
input.txt
gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 [generates ELF executable, for Linux]
Generates symbol _binary__input_txt_start.
Accepts symbol _binary__input_txt_start (with underline).
i586-mingw32msvc-gcc (GCC) 4.2.1-sjlj (mingw32-2) [generates PE executable, for Windows]
Generates symbol _binary__input_txt_start.
Accepts symbol binary__input_txt_start (without underline).
Apparently this feature is not present in OSX's ld, so you have to do it totally differently with a custom gcc flag that they added, and you can't reference the data directly, but must do some runtime initialization to get the address.
So it might be more portable to make yourself an assembler source file which includes the binary at build time, a la this answer.