How to import a class from a DLL? (#import was not closed Error)

 

I am trying to import a complete class from a DLL. But I have some errors while compiling.

Error 1 - #import was not closed

Error 2 - Sum - Member function was no defined.


1 - I compiled the dll using C++ and 64bits

2 - I put the DLL inside of this Path C:\....\MetaQuotes\Terminal\...\MQL5\Libraries

3 - I renamed the (.h) file extension to (.mqh) and i put it inside of C:\....\MetaQuotes\Terminal\...\MQL5\Include

4 - And I allow the use of dll in the MT5 options.


What am I doing wrong?

These are the test codes:


TestDLL.mq5

//+------------------------------------------------------------------+
#import "MyDLL.dll"
   class MyDLL;                             //-->it doesn't work
   double MyDLL::Sum(double x, double y);   //-->it does't work 
#import
#property strict
//+------------------------------------------------------------------+
MyDLL testdll;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   PrintFormat("%f", testdll.Sum(3, 5) );
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{    
}


main.h

#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C"
{
#endif

    class DLL_EXPORT MyDLL
    {
    public:
        MyDLL(){}
        ~MyDLL(){}
        double Sum(double x, double y);
    };

#ifdef __cplusplus
}
#endif

#endif // __MAIN_H__

main.cpp

#include "main.h"

// a sample exported function
 double MyDLL::Sum(double x, double y)
 {
     return x+y;
 }

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}

Thank you so much!!

Files:
testDLL.mq5  1 kb
MyDLL.zip  2 kb
 
karp wak:

I am trying to import a complete class from a DLL. But I have some errors while compiling.

does your dll work properly in any c++ project ? (for the test)

- I doubt - you didn't export anything

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

you #define DLL_EXPORT __ , but  I see no defined APIENTRY... - your dll is not correct about the export (test it first in c++ when doing it in c++)

p.s.

MQL (as I know) do not allow import/export classes from dll, just functions - your errors say exactly about this (#import does not work with classes from dll- at least in MQL4, I didn't test in MQL5)

 

Quick example of function like this:

.h

#ifndef _myDllMQL_myDllMQL_h
#define _myDllMQL_myDllMQL_h

#define DllImport extern "C" __declspec(dllimport)
#define DllExport extern "C" __declspec(dllexport)

#ifdef flagDLL
        #define DLLIMPORT __declspec(dllexport)
#else
        #define DLLIMPORT __declspec(dllimport)
#endif



#ifdef __cplusplus
extern "C" {
#endif
 
DLLIMPORT void __stdcall fnFillArray(int *arr,const int arr_size); 

#ifdef __cplusplus
}
#endif

#endif

.cpp

#include <windows.h>


#include "myDllMQL.h"

// https://www.mql5.com/ru/articles/18
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason,  LPVOID lpReserved)
{
        switch (reason) {
        case DLL_PROCESS_ATTACH:
                break;
        case DLL_PROCESS_DETACH:
                break;
        case DLL_THREAD_ATTACH:
                break;
        case DLL_THREAD_DETACH:
                break;
        }
        return TRUE;
}


DLLIMPORT void __stdcall fnFillArray(int *arr,const int arr_size)
  {
//--- check input parameters
   if(arr==NULL || arr_size<1) return;
//--- fill with values
   for(int i=0;i<arr_size;i++) arr[i]=i;
  }

and such - DLLIMPORT void __stdcall fnFillArray(int *arr,const int arr_size) -  is the export (with _stdcall calling convention & predefined DLLIMPORT)

// a sample exported function -- // no class needed

 

Hi. Yes, the DLL worked in my test. I thik it happened because i compiled my .exe like this.

(is just a summary--->)   g++  test.dll   myCode.cpp

But anyway it was my first .dll ... i don't kneew how to make it correctly to use with a #import directive (i will try your method).

It will be a shame if that doesn't work for importing entire classes to MT5. This example was just a test. I really need to export complex objects.

Thank you so much for your help

 
karp wak #:


(is just a summary--->)   g++  test.dll   myCode.cpp 

I compiled with Release link options

-Wl,--kill-at

otherwise it didn't work... I do not know your system, but I'm in Windows (not Linux) in U++ IDE (not VisualStudio), -- anyway search yourself if flag "--kill-at" something matters for your dll-project... but anyway you shouldn't compile .exe but .dll (as you did in command-line) & the project from the very beginning of its creation preferably be dll
 
karp wak #:
   

 for importing entire classes to MT5. This example was just a test.

I just saw 1 article (but in Russian and in MQL5 - but I'm using MQL4) -- well, and I didn't test it, but you can see the code here ...

at a glass I see CSuperClass export from .ex5 (not dll) & then some inheritance from it... but I didn't like such difficulties, therefore didn't test this example 

karp wak # :    

 I really need to export complex objects.

it is not so easy - but was also described in Russian here ...

also at a glance (because it seems not the most beautiful solution) -- you can calculate the size of your type (like fields int+char+long=4+1+8) and then use memcpy ... (and frankly speaking, it is how to survive without dll)

p.s.

here I already wrote my views on the topic (client getting pointer to the class object from compiled library -- and doesn't matter if it is either .ex5-compiled-library or dll-compiled-library) ...

(it is not very easy even in C++  because of possible differencies of compilers, I assume much more factors are  meaningful when speaking about pointers exported/imported between languages) ... you should know how the memory works & especially what is a compiled-code (machine-code) - in order to understand the limitations of your chosen application-architecture... I really do not understand why not exporting just functions... and have not need to test complex-types yet in such conditions (therefore can not say more)

Используйте EX5-библиотеки для продвижения своих разработок
Используйте EX5-библиотеки для продвижения своих разработок
  • www.mql5.com
С помощью сокрытия реализации функций/классов в ex5-файл вы сможете делиться своими ноу-хау алгоритмами с другими программистами, создавать общие проекты и продвигать их в сети. И пока команда MetaQuotes всеми силами приближает возможность прямого наследования классов из ex5‑библиотек, мы реализуем данную возможность уже сейчас.
 
I'm going to study all the options that you give me.
There is no problem with the Russian language, I will use google translater to read it.
Thank you very much for taking the time to help me.
I am really very grateful.
 
karp wak #:
I'm going to study all the options that you give me.
There is no problem with the Russian language, I will use google translater to read it.
Thank you very much for taking the time to help me.
I am really very grateful.

You can select the other language for this article:

 
Sergey Golubev #:

You can select the other language for this article:

Great!! Thank you so much!!

 
JeeyCi #:

.ex5 (not dll) 

just one remark else:

.ex-files are being compiled statically(as if its functions become the part of the whole code)... and dll is the dynamic library that is a *shared* library - it shares the same memory with e.g. EA or etc., that means the same quantity of bytes, where your data is situated should not be changed (just rearranged can be)

And remember :

Structures that contain dynamic arrays, strings, classes, other complex structures, as well as static or dynamic arrays of the enumerated objects, can't be passed as a parameter to an imported function.

Generally, functions imported from the library at a client-side == is equal to the sense "exported from the library" at dll-side ...

but import/export of classes is more tricky because of compiler (different for different languages)... and .ex-files are being statically compiled (as I know) - therefore less problems can be...

That's all & Good luck

p.s.

if you lack some stuff in MQL, instead of creating DLL you can try already integrated Python (if it helps - anyway the appropriate library already exists)

Documentation on MQL5: Integration / MetaTrader for Python
Documentation on MQL5: Integration / MetaTrader for Python
  • www.mql5.com
MetaTrader for Python - Integration - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
JeeyCi #:

just one remark else:

.ex-files are being compiled statically(as if its functions become the part of the whole code)... and dll is the dynamic library that is a *shared* library - it shares the same memory with e.g. EA or etc., that means the same quantity of bytes, where your data is situated should not be changed (just rearranged can be)

And remember :

Generally, functions imported from the library at a client-side == is equal to the sense "exported from the library" at dll-side ...

but import/export of classes is more tricky because of compiler (different for different languages)... and .ex-files are being statically compiled (as I know) - therefore less problems can be...

That's all & Good luck

p.s.

if you lack some stuff in MQL, instead of creating DLL you can try already integrated Python (if it helps - anyway the appropriate library already exists)

Thanks for that information about static and dynamic libraries !! I'll keep it in mind.

And yes, in the future I will like to experiment a little with Python and neural networks. I really want to do it !! XD

Thank you very much for your help!!