Cure
A small library that interfaces Elixir-code with C/C++ programs using Erlang/Elixir Ports. Provides Mix tasks to kickstart the development process.
Example
The following example loads a program called "program" which is located in the ./c_src/ directory.
# Open the Port to the C/C++ program:
{:ok, server_pid} = Cure.load "./c_src/program"
# Sending and receiving data:
# Option 1 (synchronous):
data = server_pid |> Cure.send_data("Testing 1, 2, 3!", :sync)
# Option 2 (asynchronous):
server_pid |> Cure.send_data(<<1, 2, 3, 4>>, fn(data) ->
# Process the received data here.
IO.inspect data
end)
# Option 3 (asynchronous):
server_pid |> Cure.send_data("More data!")
receive do
{:cure_data, data} ->
# Process the received data here.
IO.inspect data
end
# Close the program:
server_pid |> Cure.stopBy default, Cure starts a supervisor which supervises all of its children (a child in this case is a GenServer that communicates with a C-program). A child is added to the supervision tree with Cure.load(program_name). If you don't want this behaviour, you can also directly start a server with one of the following lines of code:
# Option 1:
{:ok, server_pid} = Cure.Server.start_link "program_name"
# Option 2:
{:ok, server_pid} = Cure.Server.start "program_name"If you want to use a Port directly, you can use the following functions (currently only supports synchronous communication):
port = Cure.Port.load("program_name")
result = port |> Cure.Port.send_data("123456789")
port |> Cure.Port.closeExamples that use Cure can be found at the following links:
Getting started
Add the Cure dependency to your mix.exs file:
def deps do
[{:cure, "~> 0.3.4"}]
endFetch & compile dependencies
mix deps.get
mix deps.compileStart developing in C/C++
Generate the necessary base files to communicate between C/C++ and Elixir:
mix cure.bootstrapCompile your C/C++ code (needed after each modification of your code)
mix compile.cureIf you have dependencies that also use Cure:
mix compile.cure.deps
Another option is to add the last 2 tasks to your mix.exs to compile all code automatically when you type mix.compile:
def project do
[...,
compilers: Mix.compilers ++ [:cure, :"cure.deps"],
...]
endC/C++ code
C/C++ code is currently placed in the c_src directory of your application. It can interface with Elixir-code based on 2 important functions:
- read_msg to read data coming from Elixir;
- send_msg to send data to Elixir.
These helper-functions interface with Elixir by sending/receiving data via stdin or stdout. (Right now it's only possible to send messages up to 64KiB.)
To be able to use the send and receive functions, you need to add the following include:
#include <elixir_comm.h>The code for these functions is mostly based on the following link.
Makefile
The command "mix cure.bootstrap" generates a basic Makefile (in ./c_src/) that handles the compilation of all your C-code. This file is only generated if it doesn't exist yet so it's safe to add modifications for when your C-files need extra includes to compile properly.
The command "mix cure.make" uses the Makefile to compile all your C/C++ code.