Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load a C++ DLL into matlab which calls functions in another DLL

Tags:

c++

dll

call

For learning purposes, I'm trying to load a DLL into MATLAB which calls functions defined in another DLL. I'm new to all of this, and haven't yet been able to figure out how I would go about doing this, and nor have I managed to find any relevant resources.

I wrote a small DLL in C++ which goes 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 the source file:

//example_dll.cpp
#include <stdio.h>
#include "example_dll.h"

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

This I built using MinGW w64 and loaded into matlab using loadlibrary('example_dll') without any problems.

I now want to define the function

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

In another DLL, (let's call it DLL2) and to call that function from my example_dll. What would be the easiest way to do it?

I would appreciate a short example code (preferably for run-time dynamic linking, and without the use of module definition (.def) files) or a link to a relevant resource on the interwebs. Thanks!

SOLUTION TO SIMPLE EXAMPLE:

I think I got the solution. It seems to be working anyway.

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

here it 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 the 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's 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 that the MATLAB shared library interface supports C library routines only and not C++ classes.

My idea of a workaround is to use an intermediate DLL to act as an interface between MATLAB and the DLL who's classes I intend to access. Is there a better way of doing this?

FURTHER QUESTIONS:

Can anyone please explain the significance of the line typedef int (__stdcall * pICFUNC)(int); as applied here? What would I have 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
like image 994
Ali Haroon Avatar asked Oct 31 '22 14:10

Ali Haroon


1 Answers

Further question 1

The following definition

typedef int (__stdcall * pICFUNC)(int);

defines a new type pICFUNC which is a pointer to a function which takes an int and returns an int. Also, the function must be called according to the __stdcall calling convention, which specifies how arguments must be passed and how to retrieve the return value. This link explains typedef with function pointers. Have a look also at the following section, Using typedef with type casts, since on line

Double = pICFUNC(lpfnGetProcessID);

pICFUNC is used to cast instead.

Further question 2

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

int add(int num);

you could implement the following functions:

MyClass *createInstance(){
    return new MyClass();
}

void destroyInstance(MyClass *ptrMyClass){
    delete ptrMyClass;
}

These function need to be extern "C" and you could import them with GetProcAddress. Then, it would be just a matter of creating an instance, calling its methods through the pointer and eventually destroying it.

EDIT: Some hints for the implementation

Import the function to create the instance

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

Declare a proper pointer type for the function (returns a MyClass*, no arguments)

typedef MyClass* (__stdcall * pCREATINST)();

Cast lpfnCreateInstance

pCREATINST createInstance;

createInstance = pCREATINST(lpfnCreateInstance)

Create your instance

MyClass *myInstance = creatInstance();

Then you don't need a wrapper for add, you can just call it from your pointer.

int res = myInstance->add(123);

You should do the same for destroyInstance, being careful with the types Please note that I can't test this code, but it should be the right approach.

like image 154
Marco Guerri Avatar answered Nov 04 '22 12:11

Marco Guerri