Using OpenCV in Erlang NIF. How?

Hello all!
Trying to use OpenCV shared libs in Erlang NIF. When trying to run it in Erlang VM heving this error:

{error,{load_failed,"Failed to load NIF library: 'dlopen(/Prototypes/Erlang/OpenCV/WriteStream_v1/_build/default/lib/write_stream_v1/priv/, 0x0002): symbol not found in flat namespace (__ZN2cv12VideoCapture4openERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi)'"}}

This error definitely because Erlang VM can’t find automatically OpenCV shared libs. How to make this OpenCV libraries available for Erlang VM? Should it be done vide code:paths() or erl_ddl module?

Here the code that is using by me
NIF C file:

#include <erl_nif.h>
#include <stdio.h>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//#ifdef __cplusplus
//extern "C" {

// Process variables
//static cv::VideoCapture gVideoCapture;
//VideoWriter gWriter;

ERL_NIF_TERM mk_atom(ErlNifEnv* env, const char* atom) {


	if(!enif_make_existing_atom(env, atom, &ret, ERL_NIF_LATIN1)) {
        return enif_make_atom(env, atom);

	return ret;

ERL_NIF_TERM mk_error(ErlNifEnv* env, const char* mesg) {

    return enif_make_tuple2(env, mk_atom(env, "error"), mk_atom(env, mesg));

static ERL_NIF_TERM record(ErlNifEnv* inEnvironment, int inCounter, const ERL_NIF_TERM inArguments[]) {

	ERL_NIF_TERM oOutput;

	cv::VideoCapture gVideoCapture;
//	cv::VideoWriter gWriter;"rtsp://user:pass@192.168.*.*");
	if (!gVideoCapture.isOpened()) {
		oOutput = mk_atom(inEnvironment,"not_opened");
	} else {
		oOutput = mk_atom(inEnvironment,"opened");

	return oOutput;

static ErlNifFunc nif_funcs[] = {
	{"record", 0, record}

ERL_NIF_INIT(write_stream_v1, nif_funcs, NULL, NULL, NULL, NULL);

//#ifdef __cplusplus
//} // closing brace for extern "C"

Erlang file:


-define(APPNAME, write_stream_v1).
-define(LIBNAME, write_stream_v1).

%% @doc

init() ->

	SoName = case code:priv_dir(?APPNAME) of
		{error, bad_name} ->
			case filelib:is_dir(filename:join(["..", priv])) of
				true ->
					filename:join(["..", priv, ?LIBNAME]);
				_ ->
					filename:join([priv, ?LIBNAME])
		    Dir ->
				filename:join(Dir, ?LIBNAME)
	erlang:load_nif(SoName, 0).

%% @doc
not_loaded(Line) ->

	erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}).

%% @doc
record() -> not_loaded(?LINE).

GCC parameters:

gcc -Werror ${INCLUDES} -fPIC -std=c++17 -shared -undefined dynamic_lookup -o ../priv/ write_stream_v1.cpp

What is missing by me?
Trying to build it on MacOS with Clang and GCC12.

Just tried this command:

g++-mp-12 -I/opt/local/lib/erlang/usr/include -I/opt/local/include/opencv4 -o ../priv/  -fpic -shared write_stream_v1.cpp -L/opt/local/lib/opencv4 -lopencv_calib3d -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gapi -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_videoio

When trying to build have this error:

Undefined symbols for architecture x86_64:
  "__ZN2cv12VideoCapture4openERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi", referenced from:
      __ZL6recordP18enif_environment_tiPKm in ccLrdJKN.o
  "_enif_make_atom", referenced from:
      __Z7mk_atomP18enif_environment_tPKc in ccLrdJKN.o
  "_enif_make_existing_atom", referenced from:
      __Z7mk_atomP18enif_environment_tPKc in ccLrdJKN.o
  "_enif_make_tuple", referenced from:
      _enif_make_tuple2 in ccLrdJKN.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [build] Error 1

Just made it working on Linux Ubuntu 22.04.3. All is working.
All this staff happening only for MacOS. There are difference between GCC and Clang. Could someone provide some info about how to link *.dylib files?

Unrelated nitpick:
enif_make_existing_atom() is only useful when you do not want to create new atoms. enif_make_atom() will first do a lookup and return the atom if it exists.