Load the C ++ DLL into matlab, which calls functions in another DLL

For training purposes, I am trying to load a DLL in MATLAB, which calls functions defined in another DLL. I am new to all of this and have not yet been able to understand how I will deal with this, and I have not been able to find any relevant resources.

I wrote a small DLL in C ++ that looks something like this:

//example_dll.h #ifndef EXAMPLE_DLL_H #define EXAMPLE_DLL_H #ifdef __cplusplus extern "C" { #endif #ifdef BUILDING_EXAMPLE_DLL #define EXAMPLE_DLL __declspec(dllexport) #else #define EXAMPLE_DLL __declspec(dllimport) #endif int EXAMPLE_DLL Double(int x); #ifdef __cplusplus } #endif #endif // EXAMPLE_DLL_H 

and source file:

 //example_dll.cpp #include <stdio.h> #include "example_dll.h" int Double(int x) { return 2 * x; } 

I created this using MinGW w64 and loaded into matlab with loadlibrary('example_dll') without any problems.

Now I want to define a function

 int Double(int x) { return 2 * x; } 

In another DLL (let her name DLL2) and call this function from my example_dll. What would be the easiest way to do this?

I would appreciate a short sample code (preferably for dynamic linking at runtime and without using module definition files (.def)) or a link to the corresponding resource on the networks. Thanks!

SOLUTION FOR A SIMPLE EXAMPLE:

I think I got a solution. It seems to work.

I created a DLL called interface_DLL , which I loaded into MATLAB, and from which I named my function in example_dll

there he is:

 //interface_dll.h #ifndef INTERFACE_DLL_H #define INTERFACE_DLL_H #ifdef __cplusplus extern "C" { #endif #ifdef BUILDING_INTERFACE_DLL #define INTERFACE_DLL __declspec(dllexport) #else #define INTERFACE_DLL __declspec(dllimport) #endif int INTERFACE_DLL Quadruple(int x); #ifdef __cplusplus } #endif #endif // INTERFACE_DLL_H 

and source file:

 //interface_dll.cpp #include <windows.h> #include <stdio.h> #include "interface_dll.h" #include "example_dll.h" int Quadruple(int x) { /* get handle to dll */ HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Users\\uidr0605\\Documents\\ExampleDLL\\example_dll.dll"); /* get pointer to the function in the dll*/ FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLL),"Double"); /* Define the Function in the DLL for reuse. This is just prototyping the dll function. A mock of it. Use "stdcall" for maximum compatibility. */ typedef int (__stdcall * pICFUNC)(int); pICFUNC Double; Double = pICFUNC(lpfnGetProcessID); /* The actual call to the function contained in the dll */ int intMyReturnVal = Double(x); intMyReturnVal = Double(intMyReturnVal); /* Release the Dll */ FreeLibrary(hGetProcIDDLL); /* The return val from the dll */ return intMyReturnVal; } 

I load it from MATLAB as follows:

 %loadDLL.m path = 'C:\Path\to\DLL\'; addpath(path); loadlibrary('interface_dll') i = 2; x = calllib('interface_dll', 'Quadruple', i) 

The reason I'm going through this process is because the MATLAB shared library interface only supports C library routines, not C ++ classes.

My idea of ​​a workaround is to use an intermediate DLL to work as an interface between MATLAB and the DLL that I am going to access. Is there a better way to do this?

FURTHER QUESTIONS:

Can anyone explain the value of the string typedef int (__stdcall * pICFUNC)(int); How is it applicable here? What do I need to add or what changes would I have to make if I wanted to call a function in a class in example_dll ?

EDIT: I added the following code to the example_dll header file:

 class EXAMPLE_DLL MyClass { public: int add2(int); }; #ifdef __cplusplus extern "C" { #endif MyClass EXAMPLE_DLL *createInstance(){ return new MyClass(); } void EXAMPLE_DLL destroyInstance(MyClass *ptrMyClass){ delete ptrMyClass; } #ifdef __cplusplus } #endif 
+5
source share
1 answer

Further question 1

Next definition

 typedef int (__stdcall * pICFUNC)(int); 

defines a new type pICFUNC, which is a pointer to a function that takes an int and returns an int. In addition, the function should be called in accordance with the __stdcall calling convention, which indicates how arguments should be passed and how to get the return value. This link explains typedef with function pointers. See also the following section: Using typedef with a cast type, since in a string

 Double = pICFUNC(lpfnGetProcessID); 

Instead, pICFUNC is used.

Further question 2

The following is a very simple example to give an idea. If you have a class in example_dll called MyClass that has a method

 int add(int num); 

You can implement the following functions:

 MyClass *createInstance(){ return new MyClass(); } void destroyInstance(MyClass *ptrMyClass){ delete ptrMyClass; } 

These functions must be extern "C" and you can import them using GetProcAddress. Then it would be easy to create an instance by calling its methods with a pointer and eventually destroying it.

EDIT: Some tips for implementing

Import function to create instance

 FARPROC lpfnCreateInstance = GetProcAddress(HMODULE (hGetProcIDDLL), "createInstance"); 

Declare the correct pointer type for the function (returns MyClass *, without arguments)

 typedef MyClass* (__stdcall * pCREATINST)(); 

Listing lpfnCreateInstance

 pCREATINST createInstance; createInstance = pCREATINST(lpfnCreateInstance) 

Create your own instance

 MyClass *myInstance = creatInstance(); 

Then you do not need a wrapper to add, you can just call it from your pointer.

 int res = myInstance->add(123); 

You must do the same for destroyInstance, being careful with types. Please note that I cannot verify this code, but this should be the right approach.

+2
source

Source: https://habr.com/ru/post/1206865/


All Articles