Reputation: 152
I'm trying to write and compile a custom behaviour in Erlang.
I cannot find any clear documentation on how to compile this behaviour.
-module(bla).
-export([start_link/0,behaviour_info/1]).
behaviour_info(callbacks)->
[{init,1}];
behaviour_info(_Other)->
undefined.
%% -callback init(Args :: term()) ->
%% {ok, State :: term()} | {ok, State :: term(), timeout()} |
%% {stop, Reason :: term()} | ignore.
start_link()->
init([]).
my command for comiling is :
erlc.exe .\src\bla.erl
resulting:
bla.erl:24: function init/1 undefined
Anyone an idea on writing and compiling behaviours in erlang, please? any links?
Upvotes: 3
Views: 1159
Reputation: 1689
Defining behaviour callbacks results in an obligation towards your implementation of callback module. In erlang, modules are just function containers, not classes nor interfaces. Behaviours are based on runtime module name resolution Mod:fun()
. OTP gen_server (check it) keeps its callback module name after you pass it in: gen_server:start_link(CallbackModuleName, Args, Opts)
and here is code for applying callback init/1
:
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
Name = name(Name0),
Debug = debug_options(Name, Options),
case catch Mod:init(Args) of
{ok, State} ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, State, Mod, infinity, Debug);
{ok, State, Timeout} ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, State, Mod, Timeout, Debug);
...
It's applying init/1
of passed callback module kept in Mod
parameter, gets its last value, do what you want and keep going (or not, depends on that last value).
Assume we have module bla_impl
which looks like this:
-module(bla_impl).
-behaviour(bla).
-export([init/1, start_link/0]).
start_link() -> bla:start_link(?MODULE). %% macro ?MODULE is resolved to bla_impl
init(Args) -> ... .
And now you need to say in bla which module you use by:
-module(bla).
-export([start_link/1]).
start_link(Mod) -> Mod:init([]).
or maybe better solution is to read it from configuration:
-module(bla).
-export([start_link/0]).
start_link() ->
Mod = application:get_env(bla_app, callback_module),
Mod:init([]),
...
There is many ways for doing so.
As you see there is no magic here. This would work even without -behaviour(bla)
nor specified callback with -callback
. This is just an information for compiler, tools and documentation.
From erlang documentation: Behaviours
And btw. start_link
function should spawn another process and link to it.
start_link(Mod) ->
spawn_link(Mod, init, [[]]).
Upvotes: 2