将一个C++ DLL加载到matlab中,该matlab调用另一个DLL中的函数

Ali*_*oon 5 c++ dll call

出于学习目的,我正在尝试将DLL加载到MATLAB中,该MATLAB调用另一个DLL中定义的函数.我是所有这一切的新手,还没有弄清楚我将如何做到这一点,也没有设法找到任何相关的资源.

我在C++中编写了一个小DLL,它是这样的:

//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
Run Code Online (Sandbox Code Playgroud)

和源文件:

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

int Double(int x)
{
        return 2 * x;
}
Run Code Online (Sandbox Code Playgroud)

我使用MinGW w64构建并使用loadlibrary('example_dll')没有任何问题加载到matlab中.

我现在想要定义这个功能

int Double(int x)
{
        return 2 * x;
}
Run Code Online (Sandbox Code Playgroud)

在另一个DLL中,(让我们称之为DLL2)并从我的example_dll中调用该函数.最简单的方法是什么?

我将很感激一个简短的示例代码(最好是运行时动态链接,不使用模块定义(.def)文件)或链接到互联网上的相关资源.谢谢!

简单解决方案的解决方案:

我想我得到了解决方案.无论如何它似乎都在起作用.

我创建了一个名为DLL的DLL interface_DLL,我将其加载到MATLAB中并从中调用了我的函数example_dll

这里是:

//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
Run Code Online (Sandbox Code Playgroud)

和源文件:

//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; 
}
Run Code Online (Sandbox Code Playgroud)

我从MATLAB加载它如下:

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

我正在经历这个过程的原因是MATLAB共享库接口仅支持C库例程而不支持C++类.

我对解决方法的想法是使用中间DLL作为MATLAB和我打算访问的类的DLL之间的接口.有没有更好的方法呢?

进一步的问题:

任何人都可以解释typedef int (__stdcall * pICFUNC)(int);这里应用的线的重要性吗?如果我想调用类中的函数,我需要添加什么或者我需要做些什么更改example_dll

编辑:我将以下代码添加到example_dll头文件中:

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
Run Code Online (Sandbox Code Playgroud)

Mar*_*rri 2

进一步问题1

以下定义

typedef int (__stdcall * pICFUNC)(int);
Run Code Online (Sandbox Code Playgroud)

定义了一个新类型 pICFUNC,它是一个指向接受 int 并返回 int 的函数的指针。此外,必须根据 __stdcall 调用约定来调用该函数,该约定指定必须如何传递参数以及如何检索返回值。此链接解释了 typedef 和函数指针。另请参阅以下部分,使用 typedef 和类型转换,因为在线

Double = pICFUNC(lpfnGetProcessID);
Run Code Online (Sandbox Code Playgroud)

pICFUNC 用于转换。

进一步问题2

下面是一个非常简单的例子来给出一个想法。如果example_dll中有一个名为MyClass的类,它有一个方法

int add(int num);
Run Code Online (Sandbox Code Playgroud)

您可以实现以下功能:

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

void destroyInstance(MyClass *ptrMyClass){
    delete ptrMyClass;
}
Run Code Online (Sandbox Code Playgroud)

这些函数需要是extern "C"并且您可以使用GetProcAddress导入它们。然后,只需创建一个实例,通过指针调用其方法并最终销毁它即可。

编辑:实施的一些提示

导入函数来创建实例

FARPROC lpfnCreateInstance = GetProcAddress(HMODULE (hGetProcIDDLL), "createInstance");
Run Code Online (Sandbox Code Playgroud)

为函数声明正确的指针类型(返回 MyClass*,无参数)

typedef MyClass* (__stdcall * pCREATINST)();
Run Code Online (Sandbox Code Playgroud)

转换 lpfnCreateInstance

pCREATINST createInstance;

createInstance = pCREATINST(lpfnCreateInstance)
Run Code Online (Sandbox Code Playgroud)

创建您的实例

MyClass *myInstance = creatInstance();
Run Code Online (Sandbox Code Playgroud)

那么你不需要 add 的包装器,你可以从你的指针调用它。

int res = myInstance->add(123);
Run Code Online (Sandbox Code Playgroud)

您应该对 destroyInstance 执行相同的操作,注意类型请注意,我无法测试此代码,但这应该是正确的方法。