README.md

# 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.

```elixir
# 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.stop
```

By 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:

```elixir
# 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):

```elixir
port = Cure.Port.load("program_name")
result = port |> Cure.Port.send_data("123456789")
port |> Cure.Port.close
```

Examples that use Cure can be found at the following links:

- [Subtitlex](https://github.com/Primordus/Subtitlex)
- [ExDSP](https://github.com/Primordus/ExDSP)

## Getting started

### Add the Cure dependency to your mix.exs file:
```elixir
def deps do
	[{:cure, "~> 0.3.4"}]
end
```
### Fetch & compile dependencies
```
mix deps.get
mix deps.compile
```

### Start developing in C/C++

- Generate the necessary base files to communicate between C/C++ and Elixir:
```
mix cure.bootstrap
```

- Compile your C/C++ code (needed after each modification of your code)
```
mix compile.cure
```

- If 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:

```elixir
def project do
  [...,
    compilers: Mix.compilers ++ [:cure, :"cure.deps"],
    ...]
end
```

## C/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:

1. read_msg to read data coming from Elixir;
2. 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:
```C
#include <elixir_comm.h>
```

- The code for these functions is mostly based on the following [link](http://www.erlang.org/doc/tutorial/c_port.html#id57564).

## 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.

## More information regarding Ports

- [Erlang documentation](http://www.erlang.org/doc/tutorial/c_port.html)
- [Elixir](http://elixir-lang.org/docs/stable/elixir/Port.html)