Troubles with zmq_bind() in ZeroMQ binding for MQL4 language - message

I am working on MT4 and used wrapper mql4zmq.dll as given in link
https://github.com/AustenConrad/mql4zmq
As I have followed all instruction and successfully loaded DLL as well as lib file at specific locations from pre-compiled. But it can not bind or connect with socket through zmq_connect(,) or zmq_bind(,). Please some one help me to solve this problem. I am posting my code here
// Include the libzmq.dll abstraction wrapper.
#include <mql4zmq.mqh>
//+------------------------------------------------------------------+
//| variable definitions |
//+------------------------------------------------------------------+
int speaker,listener,contextt;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
int major[1];int minor[1];int patch[1];
zmq_version(major,minor,patch);
Print("Using zeromq version " + major[0] + "." + minor[0] + "." + patch[0]);
Print(ping("Hello World"));
Print("NOTE: to use the precompiled libraries you will need to have the Microsoft Visual C++ 2010 Redistributable Package installed. To Download: http://www.microsoft.com/download/en/details.aspx?id=5555");
contextt = zmq_init(1);
speaker = zmq_socket(contextt, ZMQ_PUB);
listener = zmq_socket(contextt, ZMQ_SUB);
// Subscribe to the command channel (i.e. "cmd").
// NOTE: to subscribe to multiple channels call zmq_setsockopt multiple times.
zmq_setsockopt(listener, ZMQ_SUBSCRIBE, "");
if (zmq_bind(speaker,"tcp://127.0.0.1:5555") == -1)
{
Print("Error binding the speaker!");
return(-1);
}
There is problem in
if ( zmq_bind( speaker, "tcp://127.0.0.1:5555" ) == -1 )
It returns -1 and does not bind.
I have tried every possible thing to solve this mystery but failed.
Please let me know if I am mistaken!!!

Yes, address/port-in use may block .bind() / .connect()
As solved in the comments above, there is
another post with a similar solution of the same root-cause why the well-formed ZeroMQ-code was still not able to .bind()
Address/port release/re-use is O/S-dependent resource-management issue. Be carefull once developing for a production-grade operations.

Related

Call libc function from JNA

I use a C library from Java through JNA and one function does not flush properly (since the output appear all at once on program end). I have tried Java side System.out.flush(); with no luck.
In brief, I would like to call C fflush(stdout) from Java. With JNA already there (thus would prefer if no additional library) and without C to write.
I am aware of JNA Library mapping as in this question but that seems overkill to me.
The JNA library wrapping way code is actually not so heavy (at least for the flush all behavior).
protected interface CLibrary extends Library
{
static CLibrary clib = (CLibrary) Native.loadLibrary ("c", CLibrary.class);
int fflush (Pointer stream);
}
/* ... */
CLibrary.clib.fflush (null);
JNA also offer late binding method and these oneliners will do what you want
NativeLibrary.getInstance ("c").getFunction ("fflush").invokeInt (new Object[]{0});
// even shorter
Function.getFunction ("c", "fflush").invokeInt (new Object[]{0});
The tedious part comes when you want to limit flushing to stdout. You have to deal with vendor-specific code (stdout is either defined as a macro expanding to an array, Amtel avr-libc, to a function call, Microsoft msvcrt, or a pointer in GNU libc).
For the libc, you might use (two lines for legibility)
Pointer stdout = NativeLibrary.getInstance ("c").getGlobalVariableAddress ("stdout").getPointer (0);
Function.getFunction ("c", "fflush").invokeInt (new Object[]{stdout});
Adding this answer for Win32 / Win64 users, complementing FabienAndre's for GNU libc.
Selectively flushing the stdout stream calling the system's c library's fflush method via jna is hard and cumbersome. As FabienAndre already mentioned, it is difficult to get a hold of the stdout macro definition. For msvcrt (the Win32 / Win64 C library) it is defined via a function call to __iob_func(); the latter returning a pointer to an array of FILE structures. At index 0 is stdin, index 1 is stdout and index 2 is stderr. So for flushing stdout you even need to know the size of the FILE structure, of course, it is different for Win32 and Win64 ...
The following example is tested under Win64 but ought to work under Win32. It was inspired by the thread JNA solutions to catch stdout/stderr of DLL.
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JnaTest {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("msvcrt" , CLibrary.class);
Pointer __iob_func();
void printf(String format, Object... args);
int fflush (Pointer stream);
}
public static void main(String[] args) {
int sizeOfFileStructure = Platform.is64Bit() ? 48 : 32;
Pointer stdout = CLibrary.INSTANCE.__iob_func().share(sizeOfFileStructure);
CLibrary.INSTANCE.printf("Hello, World\n");
CLibrary.INSTANCE.fflush(stdout);
}
}

Services and Control points using libupnp SDK for ubuntu 12.04

How to make a service or control point using libupnp SDK?!
I didn't understand the documentation attached with this SDK, I don't know from where to start ?!
Can you help me in that and refer me to some helping tutorials ?!
Thanks!
Yes I know, this is a very old question but still had no answer. I came here from google because I also was looking for an entry to use the libupnp SDK aka Portable SDK for UPnP* Devices, but without success. So I will share how I got it with some effort to find things.
I'm using Debian Stretch. So first I installed:
~$ sudo apt install libupnp6 libupnp6-dev libupnp6-doc
Then have a look at the documentation (of course ;) in /usr/share/doc/libupnp6-doc/html/modules.html. One of the problems was that I wasn't able to find this document online. With the UPnP API I started with this simple program, that searches for upnp devices on the local network. Just set INTERFACE[] and SEARCH_DURATION_SECONDS for what you need.
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include <upnp/upnp.h>
constexpr char INTERFACE[] = "eth0";
constexpr int SEARCH_DURATION_SECONDS = 5;
int callback_event_handler(Upnp_EventType event_type, void* event, void* cookie)
{
std::string str;
switch (event_type) {
case UPNP_DISCOVERY_SEARCH_RESULT:
str = "UPNP_DISCOVERY_SEARCH_RESULT";
break;
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
str = "UPNP_DISCOVERY_SEARCH_TIMEOUT";
break;
default:
std::cout << "Called callback_event_handler with ignored event" << std::endl;
return 0;
}
std::cout << "Executing callback_event_handler with event type " << str << std::endl;
std::cout << (char*)cookie << std::endl;
return 0;
}
int main()
{
constexpr char cookie[] = "Free custom data, usable in the callback function.";
UpnpClient_Handle client_handle = -1;
UpnpInit2(INTERFACE, 0);
UpnpRegisterClient(callback_event_handler, &cookie, &client_handle);
UpnpSearchAsync(client_handle, SEARCH_DURATION_SECONDS, "upnp:rootdevice", cookie);
std::this_thread::sleep_for(std::chrono::seconds(SEARCH_DURATION_SECONDS + 1));
UpnpFinish();
}
The search target (ST) upnp:rootdevice at UpnpSearchAsync(..) determins what to search. For other search targets look at UPnP Device Architecture 1.0, chapter 1.2.2 Discovery: Search: Request with M-SEARCH.
I compiled the program with:
~$ g++ -std=c++11 -pedantic-errors -Wall -lpthread -lupnp upnpsearch.cpp -o upnpsearch
If you execute it and you have UPnP devices on your local network you should get an output something like this:
Executing callback_event_handler with event type UPNP_DISCOVERY_SEARCH_RESULT
Free custom data, usable in the callback function.
Called callback_event_handler with ignored event
Called callback_event_handler with ignored event
Executing callback_event_handler with event type UPNP_DISCOVERY_SEARCH_RESULT
Free custom data, usable in the callback function.
Executing callback_event_handler with event type UPNP_DISCOVERY_SEARCH_TIMEOUT
Free custom data, usable in the callback function.
Here you see that two UPnP devices are online.

How do you run a DART application as a windows service?

I've been researching the possibility of using the DART language for my next project. The only thing really holding me back at this point is that I'm unable to find a way to run a DART application as a windows service. I have run searches on Google and read through much of the documentation on the DART website. Most of the information I found was related to creating a server in DART but nothing regarding windows services.
Can someone either point me at directions or detail the steps necessary to do so?
Thanks,
Jon
=== Latest Update ===
My original answer consisted of using C and Dart FFI to boostrap the Windows Service. However, none of this is really needed as a much, much, simpler solution can be had by using Docker with Windows Containers.
Instead of actually running the application as a Windows Service, the alternative is to compile it to an executable Windows console application, create a Docker file and a Windows Docker image that will include that application. On the server you will need docker and you can simply run the image with a --restart option. To test this out, Windows 10 supports Docker with Windows containers.
So, the simple solution is, we don't really need to run Dart code as a Windows Service, because we can run it as a docker container on the server.
=== Original Answer ===
I am arriving really late to the game, but I figured a way around this problem without having to use 3rd party applications.
My solution is kind of an hack, but hey, it works. I am compiling the dart application as an executable and then registering it as a Windows Service, using sc.exe create. The issue with sc.exe create is that the main function of the application needs to perform some extra steps to inform Windows that it is running. If this isn't done, Windows service gets stuck in a "Starting state".
I don't think there is a pub package available to perform this duty. However, there are 2 things we can use: Dart:FFI, and the following article from Mohit Arora that explains how to create a Windows Service in C++. https://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus
I grabbed Mohit's code and made a ton of changes (including backporting it to C, because... C++)
C
Here's the full code of the Service.c file:
// Provides an API for Dart console applications to
// integrate themselves as Windows Services
// The entry point to this API is the Init(...)
// function at the bottom of this file.
// The Init(...) function registers the ServiceMain(...)
// function as the actual windows service function.
// the ServiceMain function does the following:
//
// 1. Registers the ServiceCtrlHandler(...) function
// as the service control handler, which is essentially
// tasked to handle control requests (in this case we
// are only handling the request to stop the service).
//
// 2. Creates an event object that and then waits indefinitely
// for the event to be set.
//
// The ServiceCtrlHandler(...) function responds to a
// close request by setting the event created by the
// ServiceMain(...) function, essentially freeing
// the latter from the indefinite wait and terminating
// it.
// The functions in this file don't actually
// do any work, but keep the Windows Service
// alive. The work be initiated by the calling
// application either before or after the call to Init(...).
// Because this was developed for the purpose
// of enabling Dart applications to run as
// Windows Services, it it the Dart Application
// that needs to call Init(...) using Dart FFI.
// It must also be the Dart Application to
// spawn an isolate that does the actual work
// before the call to Init(...)
#include <Windows.h>
#include <tchar.h>
#include "service.h"
SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
LPWSTR w_service_name;
void UpdateStatus(
DWORD newState,
DWORD checkPoint,
DWORD exitCode,
DWORD controlsAccepted)
{
g_ServiceStatus.dwControlsAccepted = controlsAccepted;
g_ServiceStatus.dwCurrentState = newState;
g_ServiceStatus.dwWin32ExitCode = exitCode;
g_ServiceStatus.dwCheckPoint = checkPoint;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
}
// Responds to control events. This implementation is
// only responding to the SERVICE_CONTROL_STOP event
// This method signals the ServiceMain function
// that it can stop waiting before terminating.
void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
if (CtrlCode != SERVICE_CONTROL_STOP || g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
return;
UpdateStatus(SERVICE_STOP_PENDING, 4, 0, 0);
SetEvent(g_ServiceStopEvent);
}
void InitServiceStatus()
{
ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
UpdateStatus(SERVICE_START_PENDING, 0, 0, 0);
}
// This function essentially creates an event object
// and enters a holding pattern until that event object
// is set by the ServiceCtrlHandler(...) in response
// to a close request.
// The function doesn't actually do any work,
// except to keep the Windows Service alive.
void WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
g_StatusHandle = RegisterServiceCtrlHandler(w_service_name, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
return;
InitServiceStatus();
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
UpdateStatus(SERVICE_STOPPED, 1, GetLastError(), 0);
return;
}
UpdateStatus(SERVICE_RUNNING, 0, 0, SERVICE_ACCEPT_STOP);
while (WaitForSingleObject(g_ServiceStopEvent, INFINITE) != WAIT_OBJECT_0)
;
CloseHandle(g_ServiceStopEvent);
UpdateStatus(SERVICE_STOPPED, 3, 0, 0);
}
LPWSTR get_service_name(const char* service_name)
{
int max_count = strlen(service_name);
int size = max_count + 1;
LPWSTR ret = malloc(sizeof(wchar_t) * size);
size_t outSize;
mbstowcs_s(&outSize, ret, size, service_name, max_count);
return ret;
}
/// This is the entry point that should be called
/// by the Dart application (or any application
/// of a similar kind of platform) in order to
/// integrate itself as a Windows Service.
/// It registers the ServiceMain(...) function
/// as the service main function. Please consult
/// the comments at that function to understand
/// what it does.
int init(const char* service_name)
{
w_service_name = get_service_name(service_name);
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{w_service_name, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
return GetLastError();
}
The Service.h header file is, naturally, a lot smaller:
#pragma once
#ifdef WINSERVICE_EXPORTS
#define WINSERVICE_API __declspec(dllexport)
#else
#define WINSERVICE_API __declspec(dllimport)
#endif
WINSERVICE_API int init(const char* service_name);
Just make sure you add WINSERVICE_EXPORTS to one of the definitions or replace it by the corresponding definition in your project.
Dart
I also needed to perform a few changes from the Dart side. Here's my prototype:
import 'dart:ffi' as ffi;
import 'dart:io';
import 'dart:isolate';
import 'package:ffi/ffi.dart';
import 'package:grpc/grpc.dart' as grpc;
// These two types represent the
// Init(...) function of the C API
typedef init_func = ffi.Int32 Function(ffi.Pointer<Utf8>);
typedef Init = int Function(ffi.Pointer<Utf8>);
// Entry point to the Dart application.
// When run as a Windows Service,
// this is still the entry point.
// This code is not embeded but is started
// as a regular console application.
void main() async {
final init = createInit();
// Starts the actual work in a separate Isolate
await Isolate.spawn(run, 'message');
final serviceName = Utf8.toUtf8('MProto_Server_from_Dart');
// calls the Init(...) function
var result = init(serviceName);
if (result != 0) return;
// blocks this Isolate indefinitely from continuing
while (true) {
sleep(Duration(days: 365));
}
}
// Creates the instance of the proxy to the Init(...)
// function.
Init createInit() {
final path =
r'[PATH to the C compiled DLL]';
final dylib = ffi.DynamicLibrary.open(path);
// ignore: omit_local_variable_types
final Init init =
dylib.lookup<ffi.NativeFunction<init_func>>('init').asFunction();
return init;
}
// Performs the actual work that needs to
// be done, in this case, we are hosting
// a gRPC service, but this should
// work with any other kind of
// payload, namely other types of
// http services.
void run(String message) async {
print('inside isolate');
var server = grpc.Server(
[
// my service classes
],
);
await server.serve(port: 5001);
}
There's no difference in using Dart for a Windows service as any other executable; you just need to call dart.exe with the correct arguments.
However, Windows doesn't support running arbitrary exes as Windows Services, as they require a little metadata/bootstrapping. I've had good experiences with NSSM - the Non-Sucking Service Manager. In the comments, SC.exe was suggested; but I was unable to get it running on the latest version of Windows Server :(
look at dart package dart_windows_service_support
He use dart:ffi and a dll file enables dart to run in Windows service mode
https://pub.dev/packages/dart_windows_service_support
Use WinSW
WinSW wraps and manages any application as a Windows service.
Create the service directory in your project.
Find the latest release of WinSW on GitHub, you are very likely looking specifically for WinSW-x64.exe. Copy this file under the service directory in your project and rename it to your linking, e.g. service\MyApp-Service.exe.
Create a configuration file for your service service\MyApp-Service.xml with the sample configuration below.
Run .\MyApp-Service.exe install from command line. Your service should be listed in Windows services.
Sample config XML:
<service>
<id>MyApp</id>
<name>My App</name>
<description>My App's description</description>
<executable>C:\tools\dart-sdk\bin\dart.exe</executable>
<workingdirectory>C:\path\to\project</workingdirectory>
<arguments>lib/main.dart</arguments>
<log mode="roll"></log>
<priority>high</priority>
</service>

C++ Builder 2010 Strange Access Violations

I've got a program that is to become part of an already existing, larger product which is built using C++ Builder 2010.
The smaller program does not (yet) depend on C++ Builder. It works fine in MS Visual Studio, but with C++ Builder it produces strange access violations.
Please let me explain this.
Depending on the code and on compiler settings, access violations happen or do not happen. The access violations are reproducible: When the program is built then the access violation does never occur or it does always occur at the same place. If the program is rebuilt with the same settings, it will show the same behavior. (I'm really glad about that).
The access violation happens at places where the delete operator is called. This can happen (depending on compiler settings and exact code) inside certain destructors, including destructors of own classes and inside the destructor of std::string.
The following things make the access violation less likely:
Build with "Debug" settings (instead of "Release").
No compiler optimizations.
Compiler switch "Slow exception epilogues".
Static RTL instead of dynamic.
Derive exceptions from std::exception instead of Borland's Exception class.
Use less "complicated" expressions (e.g. use "string s = "..." + "..."; throw SomeException(s);" instead of "throw
SomeException(string("...") + "...");")
Use try... __finally with manual cleanup instead of automatic variables with destructors.
Use a small console application instead a VCL windows application.
The program makes use of several C++ features, including exceptions, STL, move constructors etc. and it of course uses the heap.
I already tried some tools, none of them reported problems:
Borland's CodeGuard.
Microsoft Application Verifyer.
pageheap/gflags.
As already mentioned, there is absolutely no problem when building with MS Visual Studio.
Use of precompiled headers and incremental linking (which both seem to me are prone to errors) are disabled.
Neither the C++ Builder compiler ("enable all warnings") nor the one of Visual Studio (/W4) produces a warning that might be related to this issue.
I do not have access to another version of C++ Builder.
As the program will become part of a larger product, it is not an option to switch to a different compiler, and it is not an option to tune the compiler settings until the access violation does no longer happen. (I fear if this really should a compiler bug, the bug might show up again.)
Putting this together, I'm guessing this might result from heap corruption that is related to some compiler bug. However, I was not able to find a bug on qc.embarcadero.com. I'm guessing further this is related to cleanup code that is executed upon stack rewinding when an exception has been thrown. But, well, maybe it's only a stupid code bug.
Currently, I do not have any idea how to proceed. Any help appreciated. Thank you in advance!
tl;dr I believe the bug is that code is generated to delete the std::string from both branches of the ternary operator during stack unwinding, however only one of them was actually created of course.
Here is a simpler MCVE, which shows the problem via outputs in XE5:
#include <vcl.h>
#include <tchar.h>
#include <stdio.h>
using namespace std;
struct S
{
S() { printf("Create: %p\n", this); }
S(S const &) { printf("Copy: %p\n", this); }
void operator=(S const &) { printf("Assign: %p\n", this); }
~S() { printf("Destroy: %p\n", this); }
char const *c_str() { return "xx"; }
};
S rX() { return S(); }
int foo() { return 2; }
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
try
{
throw Exception( (foo() ? rX() : rX()).c_str() );
}
catch (const Exception& e)
{
}
getchar();
return 0;
}
This version shows the problem via output strings on the console. Check the edit history for this post to see a version that uses std::string and causes the segfault instead.
My output is:
Create: 0018FF38
Destroy: 0018FF2C
Destroy: 0018FF38
In the original code, the segfault comes from the bogus Destroy ending up calling delete on the bogus value it obtains by trying to retrieve the internal data pointer for a std::string which was actually never created at that location.
My conjecture is that the code generation for stack unwinding is bugged and tries to delete the temporary string from both branches of the ternary operator. The presence of the temporary UnicodeString does have something to do with it; as the bug did not occur in any variations where I tried to avoid that temporary.
In the debugger you can see the call stack and it is during global stack unwinding that this happens.
Phew, that was so simple that it took me some time:
#include <vcl.h>
#include <tchar.h>
#include <string>
using namespace std;
struct B
{
B(const char* c) { }
string X() const { return "xx"; }
int Length() const { return 2; }
};
struct C
{
void ViolateAccess(const B& r)
{
try
{
throw Exception(string("aoei").c_str());
}
catch (const Exception&) { }
throw Exception(((string) "a" + (r.Length() < 10 ? r.X() : r.X() + "...") + "b").c_str());
}
};
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
try
{
C c;
c.ViolateAccess("11");
}
catch (const Exception& e) { }
return 0;
}
(Preemptive comment: No, this code does not make any sense.)
Create a new console application and make sure to use the VCL. It might depend on the project settings whether there will be an access violation or not; my debug builds always crashed, release builds didn't.
Crashes with C++ Builder 2010 and XE3 trial.
Thus, bug in compiler or in VCL or in STL or whatever.

Erlang C node related question

In the tutorial provided at:
http://www.erlang.org/doc/tutorial/cnode.html
There is the following example:
/* cnode_s.c */
#include
#include
#include
#include
#include "erl_interface.h"
#include "ei.h"
#define BUFSIZE 1000
int main(int argc, char **argv) {
int port; /* Listen port number */
int listen; /* Listen socket */
int fd; /* fd to Erlang node */
ErlConnect conn; /* Connection data */
int loop = 1; /* Loop flag */
int got; /* Result of receive */
unsigned char buf[BUFSIZE]; /* Buffer for incoming message */
ErlMessage emsg; /* Incoming message */
ETERM *fromp, *tuplep, *fnp, *argp, *resp;
int res;
port = atoi(argv[1]);
erl_init(NULL, 0);
if (erl_connect_init(1, "secretcookie", 0) == -1)
erl_err_quit("erl_connect_init");
/* Make a listen socket */
if ((listen = my_listen(port))
I suspect that erl_receive_msg is a blocking call, and I don't know how to overcome this. In C network programming there is the "select" statement but in the Erlang EI API I don't know whether there is such a statement.
Basically I want to build a C node, that continuously sends messages to Erlang nodes. For simplicity suppose there is only one Erlang node.
The Erlang node has to process the messages it receives from the C node. The Erlang node is not supposed to ensure that it has received the message, not does it have to reply with the result of processing. Therefore once the message is sent I don't care about it faith.
One might think that one could modify the code as:
...
if (emsg.type == ERL_REG_SEND) {
...
while(1) {
//generate tuple
erl_send(fd, fromp, tuple);
//free alloc resources
}
...
}
This will produce an infinite loop in which we produce and consume (send) messages.
But there is an important problem: if I do this, then the C node might send too many messages to the Erlang node (so there should be a way to send a message from the Erlang node to the C node to slow down), or the Erlang node might think that the C node is down.
I know that the questions must be short an suite (this is long and ugly), but summing up:
What mechanism (procedure call, algorithm) one might use to develop an eager producer in C for a lazy consumer in Erlang, such that both parties are aware of the underlying context ?
I use Port Drivers myself for the case you are describing (haven't touched the C nodes because I'd rather have more decoupling).
Have a look at the Port Driver library for Erlang: EPAPI. There is a project that leverages this library: Erland DBus.
Did you check the ei_receive_msg_tmo function? I suppose it works similar to the receive after construct of Erlang, so if you set timeout to 0, it will be non-blocking.
I believe erl_interface is deprecated, and ei should be used instead. This might be a complete misinformation though...
you need to take a closer look at the tutorial link that you posted. (search for "And finally we have the code for the C node client.") You will see that the author provided a client cnode implementation. It looks rational.

Resources