Skip to content

Commit 33fdafb

Browse files
author
Austen Conrad
committed
initial commit. mql4zmq.dll code.
1 parent c2ead7e commit 33fdafb

File tree

3 files changed

+360
-0
lines changed

3 files changed

+360
-0
lines changed

Diff for: mql4zmq.c

+283
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*
2+
MQL4ZMQ - MQL4 bindings for ZeroMQ
3+
4+
(c) 2012 Austen Conrad. Any of this software, or any part thereof, is allowed as long as the use complies with GPL v3.0: http://www.gnu.org/licenses/gpl-3.0-standalone.html
5+
Additionally, no warrenty of any kind is made. Use software at own risk.
6+
7+
===================================
8+
9+
The reason for all of this is that MetaTrader is a visual basic application and therefore is written using the STDCALL calling
10+
convention while ZeroMQ dll EXPORT defaults to the standard C calling convention (CDECL). If not changed, a call to
11+
libzmq.dll from MetaTrader will result in the trading terminal crashing.
12+
13+
Therefore, this file generates mql4zmq.dll which wraps each call the zmq.h exports when compiled as libzmq.dll (i.e. each function
14+
that has ZMQ_EXPORT preceeding it) as a STDCALL instead (i.e. __stdcall via WINAPI definition).
15+
16+
Additionally, MetaTrader4 has limitations on datatypes and data structures that we attempt to resolve by having the wrapping funtion
17+
inputs being of a type and in a manner that will jive with MQL4.
18+
19+
NOTE: Remember to add a link to the "libzmq.lib" file that is created upon building of libzmq to the mql4zmq project via: Add => Existing Item => ../Debug/libzmq.lib
20+
This .lib file exposes all of the exported functions of the libzmq.dll for use with our program as referenced per zmq.h.
21+
Also add the "mql4zmq.def" file to the linker input via: Properties => Configuration Properties => Linker => Input => Module Definition File,
22+
and to change the linker settings from "Windows" to "Console" via: Properties => Configuration Properties => Linker => System => Subsystem.
23+
24+
NAMING NOTE: To avoid naming collisions with the original zmq.h definitions we renamed our exported functions with 'mql4' appended to the beginning of the name.
25+
In the mql4zmq.mqh we revert the names back to the original to reduce confusion when writing experts.
26+
27+
libzmq.dll NOTE: After building the solution, copy ../../../lib/libzmq.dll to c:\Windows\SysWOW64\libzmq.dll so that our bindings and other applications can access ZeroMQ.
28+
29+
===================================
30+
*/
31+
32+
// Include the original libzmq header file.
33+
#include "../../../include/zmq.h"
34+
35+
// Handle DSO symbol visibility. This is already defined in zmq.h, but we set it here again to protect against future changes to Microsoft Visual C++ detection methods.
36+
#define ZMQ_EXPORT __declspec(dllexport)
37+
38+
// Setup the standard call specification keyword for the compiler.
39+
#define WINAPI __stdcall
40+
41+
// Hello World test function.
42+
ZMQ_EXPORT const char* WINAPI ping (const char* pong)
43+
{
44+
return(pong);
45+
}
46+
47+
/******************************************************************************/
48+
/* 0MQ versioning support. */
49+
/******************************************************************************/
50+
ZMQ_EXPORT void WINAPI mql4zmq_version (int *major, int *minor, int *patch)
51+
{
52+
zmq_version(major, minor, patch);
53+
}
54+
55+
/******************************************************************************/
56+
/* 0MQ errors. */
57+
/******************************************************************************/
58+
ZMQ_EXPORT int WINAPI mql4zmq_errno (void)
59+
{
60+
return zmq_errno();
61+
}
62+
63+
ZMQ_EXPORT const char* WINAPI mql4zmq_strerror (int errnum)
64+
{
65+
return zmq_strerror(errnum);
66+
}
67+
68+
/******************************************************************************/
69+
/* 0MQ message definition. */
70+
/******************************************************************************/
71+
ZMQ_EXPORT int WINAPI mql4zmq_msg_init (zmq_msg_t *msg)
72+
{
73+
return zmq_msg_init(msg);
74+
}
75+
76+
ZMQ_EXPORT int WINAPI mql4zmq_msg_init_size (zmq_msg_t *msg, size_t size)
77+
{
78+
return zmq_msg_init_size(msg, size);
79+
}
80+
81+
// Used to satisfy zmq_msg_init_data requirement to have a function passed to it that will free the data buffer
82+
// provided when it is no longer needed. For more info on the 'free' call see: http://www.cplusplus.com/reference/clibrary/cstdlib/free/
83+
//
84+
// NOTICE: We are no longer using this (passing NULL instead) as it was causing windows to close MetaTrader due to
85+
// thinking it was a virus since we were clearing memory that was originally allocated MetaTrader and not mql4zmq.dll
86+
void release_buffer(void *data, void *hint)
87+
{
88+
free(data);
89+
}
90+
91+
ZMQ_EXPORT int WINAPI mql4zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size)
92+
{
93+
return zmq_msg_init_data(msg, data, size, NULL, NULL);
94+
}
95+
96+
ZMQ_EXPORT int WINAPI mql4zmq_msg_close (zmq_msg_t *msg)
97+
{
98+
return zmq_msg_close(msg);
99+
}
100+
101+
ZMQ_EXPORT int WINAPI mql4zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src)
102+
{
103+
return zmq_msg_move(dest, src);
104+
}
105+
106+
ZMQ_EXPORT int WINAPI mql4zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src)
107+
{
108+
return zmq_msg_copy(dest, src);
109+
}
110+
111+
ZMQ_EXPORT void* WINAPI mql4zmq_msg_data (zmq_msg_t *msg)
112+
{
113+
return zmq_msg_data(msg);
114+
}
115+
116+
ZMQ_EXPORT size_t WINAPI mql4zmq_msg_size (zmq_msg_t *msg)
117+
{
118+
return zmq_msg_size(msg);
119+
}
120+
121+
/******************************************************************************/
122+
/* 0MQ infrastructure (a.k.a. context) initialisation & termination. */
123+
/******************************************************************************/
124+
ZMQ_EXPORT void* WINAPI mql4zmq_init (int io_threads)
125+
{
126+
return zmq_init(io_threads);
127+
}
128+
129+
ZMQ_EXPORT int WINAPI mql4zmq_term (void *context)
130+
{
131+
return zmq_term(context);
132+
}
133+
134+
/******************************************************************************/
135+
/* 0MQ socket definition. */
136+
/******************************************************************************/
137+
ZMQ_EXPORT void* WINAPI mql4zmq_socket (void *context, int type)
138+
{
139+
return zmq_socket(context, type);
140+
}
141+
142+
ZMQ_EXPORT int WINAPI mql4zmq_close (void *s)
143+
{
144+
return zmq_close(s);
145+
}
146+
147+
ZMQ_EXPORT int WINAPI mql4zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen)
148+
{
149+
return zmq_setsockopt(s, option, optval, optvallen);
150+
}
151+
152+
ZMQ_EXPORT int WINAPI mql4zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen)
153+
{
154+
return zmq_getsockopt(s, option, optval, optvallen);
155+
}
156+
157+
ZMQ_EXPORT int WINAPI mql4zmq_bind (void *s, const char *addr)
158+
{
159+
return zmq_bind(s, addr);
160+
}
161+
162+
ZMQ_EXPORT int WINAPI mql4zmq_connect (void *s, const char *addr)
163+
{
164+
return zmq_connect(s, addr);
165+
}
166+
167+
ZMQ_EXPORT int WINAPI mql4zmq_send (void *s, zmq_msg_t *msg, int flags)
168+
{
169+
return zmq_send (s, msg, flags);
170+
}
171+
172+
ZMQ_EXPORT int WINAPI mql4zmq_recv (void *s, zmq_msg_t *msg, int flags)
173+
{
174+
return zmq_recv(s, msg, flags);
175+
}
176+
177+
/******************************************************************************/
178+
/* I/O multiplexing. */
179+
/******************************************************************************/
180+
ZMQ_EXPORT int WINAPI mql4zmq_poll (zmq_pollitem_t *items, int nitems, long timeout)
181+
{
182+
return zmq_poll(items, nitems, timeout);
183+
}
184+
185+
/******************************************************************************/
186+
/* Built-in devices */
187+
/******************************************************************************/
188+
ZMQ_EXPORT int WINAPI mql4zmq_device (int device, void * insocket, void* outsocket)
189+
{
190+
return zmq_device(device, insocket, outsocket);
191+
}
192+
193+
/******************************************************************************/
194+
/* A Couple Helper Functions For Building Apps More Quickly. */
195+
/* Taken from the Z-Guide file at: https://github.com/imatix/zguide/blob/master/examples/C/zhelpers.h
196+
/******************************************************************************/
197+
198+
// Receive 0MQ string from socket and convert into C string
199+
// Caller must free returned string. Returns NULL if the context
200+
// is being terminated.
201+
ZMQ_EXPORT const char* WINAPI mql4s_recv (void* socket, int flags)
202+
{
203+
// Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h).
204+
// Hence specifing our variables right away instead of inline.
205+
char* string;
206+
int size;
207+
208+
// Initialize message.
209+
zmq_msg_t message;
210+
zmq_msg_init(&message);
211+
212+
// Receive the inbound message.
213+
if (zmq_recv (socket, &message, flags))
214+
return (NULL); // No message received
215+
216+
// Retrive message size.
217+
size = zmq_msg_size(&message);
218+
219+
// Initialize variable to hold the message.
220+
string = malloc (size + 1);
221+
222+
// Retrive pointer to message data and store message in variable 'string'
223+
memcpy (string, zmq_msg_data (&message), size);
224+
225+
// Deallocate message buffer.
226+
zmq_msg_close (&message);
227+
228+
// Return the message.
229+
string [size] = 0;
230+
return (string);
231+
}
232+
233+
// Convert C string to 0MQ string and send to socket
234+
ZMQ_EXPORT int WINAPI mql4s_send (void *socket, char *text)
235+
{
236+
// Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h).
237+
// Hence specifing our variables right away instead of inline.
238+
int result;
239+
240+
// Initialize message.
241+
zmq_msg_t message;
242+
243+
// Set the message to have a spcified length.
244+
zmq_msg_init_size (&message, strlen (text));
245+
246+
// Place the specified value of variable 'string' inside of the message buffer.
247+
memcpy (zmq_msg_data (&message), text, strlen (text));
248+
249+
// Stream the message to the specified socket.
250+
result = zmq_send (socket, &message, 0);
251+
252+
// Deallocate the message.
253+
zmq_msg_close (&message);
254+
255+
// Return the response of the zmq_send call. 0 is success, -1 is error.
256+
return (result);
257+
}
258+
259+
// Sends string as 0MQ string, as multipart non-terminal
260+
ZMQ_EXPORT int WINAPI mql4s_sendmore (void *socket, char *text)
261+
{
262+
// Strict "C" spec has to be followed because we outputing the function as 'extern "C"' (see mql4zmq.h).
263+
// Hence specifing our variables right away instead of inline.
264+
int result;
265+
266+
// Initialize message.
267+
zmq_msg_t message;
268+
269+
// Set the message to have a spcified length.
270+
zmq_msg_init_size (&message, strlen (text));
271+
272+
// Place the specified value of variable 'string' inside of the message buffer.
273+
memcpy (zmq_msg_data (&message), text, strlen (text));
274+
275+
// Stream the message to the specified socket.
276+
result = zmq_send (socket, &message, ZMQ_SNDMORE);
277+
278+
// Deallocate the message.
279+
zmq_msg_close (&message);
280+
281+
// Return the response of the zmq_send call. 0 is success, -1 is error.
282+
return (result);
283+
}

Diff for: mql4zmq.def

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
LIBRARY "mql4zmq"
2+
EXPORTS
3+
ping
4+
mql4zmq_version
5+
6+
mql4zmq_errno
7+
mql4zmq_strerror
8+
9+
mql4zmq_msg_init
10+
mql4zmq_msg_init_size
11+
mql4zmq_msg_init_data
12+
mql4zmq_msg_close
13+
mql4zmq_msg_move
14+
mql4zmq_msg_copy
15+
mql4zmq_msg_data
16+
mql4zmq_msg_size
17+
18+
mql4zmq_init
19+
mql4zmq_term
20+
21+
mql4zmq_socket
22+
mql4zmq_close
23+
mql4zmq_setsockopt
24+
mql4zmq_getsockopt
25+
mql4zmq_bind
26+
mql4zmq_connect
27+
mql4zmq_send
28+
mql4zmq_recv
29+
30+
mql4zmq_poll
31+
32+
mql4zmq_device
33+
34+
mql4s_recv
35+
mql4s_send
36+
mql4s_sendmore

Diff for: mql4zmq.h

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
MQL4ZMQ - MQL4 bindings for ZeroMQ
3+
4+
(c) 2012 Austen Conrad. Any of this software, or any part thereof, is allowed as long as the use complies with GPL v3.0: http://www.gnu.org/licenses/gpl-3.0-standalone.html
5+
Additionally, no warrenty of any kind is made. Use software at own risk.
6+
7+
===================================
8+
9+
The reason for all of this is that MetaTrader is a visual basic application and therefore is written using the STDCALL calling
10+
convention while ZeroMQ dll EXPORT defaults to the standard C calling convention (CDECL). If not changed, a call to
11+
libzmq.dll from MetaTrader will result in the trading terminal crashing.
12+
13+
Therefore, this file generates mql4zmq.dll which wraps each call the zmq.h exports when compiled as libzmq.dll (i.e. each function
14+
that has ZMQ_EXPORT preceeding it) as a STDCALL instead (i.e. __stdcall via WINAPI definition).
15+
16+
Additionally, MetaTrader4 has limitations on datatypes and data structures that we attempt to resolve by having the wrapping funtion
17+
inputs being of a type and in a manner that will jive with MQL4.
18+
19+
NOTE: Remember to add a link to the "libzmq.lib" file that is created upon building of libzmq to the mql4zmq project via: Add => Existing Item => ../Debug/libzmq.lib
20+
This .lib file exposes all of the exported functions of the libzmq.dll for use with our program as referenced per zmq.h.
21+
Also add the "mql4zmq.def" file to the linker input via: Properties => Configuration Properties => Linker => Input => Module Definition File,
22+
and to change the linker settings from "Windows" to "Console" via: Properties => Configuration Properties => Linker => System => Subsystem.
23+
24+
NAMING NOTE: To avoid naming collisions with the original zmq.h definitions we renamed our exported functions with 'mql4' appended to the beginning of the name.
25+
In the mql4zmq.mqh we revert the names back to the original to reduce confusion when writing experts.
26+
27+
libzmq.dll NOTE: After building the solution, copy ../../../lib/libzmq.dll to c:\Windows\SysWOW64\libzmq.dll so that our bindings and other applications can access ZeroMQ.
28+
29+
===================================
30+
*/
31+
32+
//Setup for "C" linkage instead of "C++" linkage.
33+
extern "C" {
34+
// Hello World test function.
35+
const char* ping (const char* pong);
36+
37+
// zhelper functions.
38+
const char* mql4s_recv (void* socket, int flags);
39+
int mql4s_send (void *socket, char *text);
40+
int mql4s_sendmore (void *socket, char *text);
41+
}

0 commit comments

Comments
 (0)