Declaring and calling the functions from inner structs in native DLLs.

 

Guys, I have to use some functions of an native DLL.

It is implemented like this in C, I think.  Notice the inner structs.

Here is the exposed struct;

In C it is called like this:

But I could not make it work in MQL5. Is it possible? 

In MQL5 I could  typdef the and expose just the libnative_ExportedSymbols structure only, for inner ones I could not find the syntax. Is it possible?

 
metadevEU:

Guys, I have to use some functions of an native DLL.

It is implemented like this in C, I think.  Notice the inner structs.

Here is the exposed struct;

In C it is called like this:

But I could not make it work in MQL5. Is it possible? 

In MQL5 I could  typdef the and expose just the libnative_ExportedSymbols structure only, for inner ones I could not find the syntax. Is it possible?

I think your post is incomplete...
 
Dominik Egert #:
I think your post is incomplete...
Oh, the images were not included. I will add it again.
 

I am posting it again @Dominik Egert:

This is the native DLL with the C functions. Notice the inner structs:
typedef struct {
  
  struct {
    struct {
      void (*forIntegers)(Byte b, Short s, Int i, Long l);
      void (*forFloats)(Float f, Double d);
    } example;
  } root;
} libnative_ExportedSymbols;



This is how it it's making it available in the build DLL:

extern libnative_ExportedSymbols* libnative_symbols(void);


Then, in the other C app, this is how it is imported:


#include "libnative_api.h"
#include "stdio.h"

int main(int argc, char** argv) {
  //obtain reference for calling Native functions
  libnative_ExportedSymbols* lib = libnative_symbols();

  lib->root.example.forIntegers(1, 2, 3, 4);
  lib->root.example.forFloats(1.0f, 2.0);

  ....
}

Notice how the inner structs are referenced in C, is it possible to do it in Mql5? I tried guessing how it works in many ways, and I read lots of documentation about the #import clause but I could not make it work.

I cannot change this DLL to remove the inner structs. 


Thanks.

 
metadevEU #:

I am posting it again @Dominik Egert:

This is the native DLL with the C functions. Notice the inner structs:
typedef struct {
  
  struct {
    struct {
      void (*forIntegers)(Byte b, Short s, Int i, Long l);
      void (*forFloats)(Float f, Double d);
    } example;
  } root;
} libnative_ExportedSymbols;



This is how it it's making it available in the build DLL:

extern libnative_ExportedSymbols* libnative_symbols(void);


Then, in the other C app, this is how it is imported:


#include "libnative_api.h"
#include "stdio.h"

int main(int argc, char** argv) {
  //obtain reference for calling Native functions
  libnative_ExportedSymbols* lib = libnative_symbols();

  lib->root.example.forIntegers(1, 2, 3, 4);
  lib->root.example.forFloats(1.0f, 2.0);

  ....
}

Notice how the inner structs are referenced in C, is it possible to do it in Mql5? I tried guessing how it works in many ways, and I read lots of documentation about the #import clause but I could not make it work.

I cannot change this DLL to remove the inner structs. 


Thanks.

The compatibility issue here is, it's a pointer to a structure.

This is your first obstacle. 

native_symbols returns an address as pointer. Only way I can think of how to access this is by creating a function that takes the structure as parameter, in MQL. Now you call this function and feed it with the return value from native_symbols.

Next obstacle are the function pointers inside the nested struct. You need to create an exact copy of that struct definition inside MQL to have it be compatible with the struct from your DLL.

The function pointers in that struct are obviously filled with a pointer to functions inside the DLL. Copy them out into a global MQL function pointer variable - inside the function you created to my explanation ^^.

This should give you access...

If I haven't misread the code completely, this is.


EDIT:

I have thought about this, and I think you need a helper DLL to actually convert the struct pointer to a native MQL struct...

Something along the lines of this (only typed, not tested):

typedef void (*funcptr_forIntegers)(char, short, int, long)
typedef void (*funcptr_forFloats)(float, double);


struct _libnative_ExportedSymbols
{
  
    struct _root 
    {
    
        struct _example
        {
            funcptr_forIntegers     integer_func;
            funcptr_forFloats       floats_func;
        } example;

    } root;

} libnative_ExportedSymbols; 


#import "my_nasty_dll"

    ulong libnative_symbols(void);

#import

#import "helper_dll"

    void convert_structptr_to_struct(_libnative_ExportedSymbols&, ulong)
    
#import



void OnStart()
{

    _libnative_ExportedSymbols mql_struct();
    
    convert_structptr_to_struct(mql_struct, libnative_symbols());


};


 
Dominik Egert #:
The compatibility issue here is, it's a pointer to a structure.

This is your first obstacle. 

native_symbols returns an address as pointer. Only way I can think of how to access this is by creating a function that takes the structure as parameter, in MQL. Now you call this function and feed it with the return value from native_symbols.

Next obstacle are the function pointers inside the nested struct. You need to create an exact copy of that struct definition inside MQL to have it be compatible with the struct from your DLL.

The function pointers in that struct are obviously filled with a pointer to functions inside the DLL. Copy them out into a global MQL function pointer variable - inside the function you created to my explanation ^^.

This should give you access...

If I haven't misread the code completely, this is.


EDIT:

I have thought about this, and I think you need a helper DLL to actually convert the struct pointer to a native MQL struct...

Something along the lines of this (only typed, not tested):

I understood. I was trying to avoid to have a extra dll in between, but it seems there is no other way.

If I cannot escape of having an extra DLL, I think it would be easier if in the helper one I just expose my methods without a nested structure. What do you think? Does it sound easier?

 
metadevEU #:

I understood. I was trying to avoid to have a extra dll in between, but it seems there is no other way.

If I cannot escape of having an extra DLL, I think it would be easier if in the helper one I just expose my methods without a nested structure. What do you think? Does it sound easier?

I am not sure, because the way this structure is defined, I could imagine the function pointers change frequently.

You need to check how to solve that.
 
Look at this article.
Getting Rid of Self-Made DLLs
Getting Rid of Self-Made DLLs
  • www.mql5.com
If MQL5 language functional is not enough for fulfilling tasks, an MQL5 programmer has to use additional tools. He\she has to pass to another programming language and create an intermediate DLL. MQL5 has the possibility to present various data types and transfer them to API but, unfortunately, MQL5 cannot solve the issue concerning data extraction from the accepted pointer. In this article we will dot all the "i"s and show simple mechanisms of exchanging and working with complex data types.
 
Alain Verleyen #:
Look at this article.
I have seen this one, but I could not find a way to reference the nested structures. 
 
Dominik Egert #:
I am not sure, because the way this structure is defined, I could imagine the function pointers change frequently.

You need to check how to solve that.
The exposed ones will not change much. I will keep some sort of well defined "interfaces". Damn, I really need to solve it...
 
metadevEU #:
The exposed ones will not change much. I will keep some sort of well defined "interfaces". Damn, I really need to solve it...
You will, don't worry...

In the end, you will have gained a pile of experience, that's much more satisfying than actually solving. In a few months, you won't remember the struggle, nor the solution, but the experience and insights you gained.