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

标签 c++ dll call

出于学习目的,我试图将一个 DLL 加载到 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

和源文件:

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

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

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

我现在要定义函数

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

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

我希望能提供一个简短的示例代码(最好用于运行时动态链接,并且不使用模块定义 (.def) 文件)或互联网上相关资源的链接。 谢谢!

简单示例的解决方案:

我想我找到了解决方案。无论如何它似乎都在工作。

我创建了一个名为 interface_DLL 的 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

和源文件:

//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; 
}

我按如下方式从 MATLAB 加载它:

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

我经历这个过程的原因是 the MATLAB shared library interface supports C library routines only and not C++ classes.

我的解决方法是使用中间 DLL 作为 MATLAB 和我打算访问的类的 DLL 之间的接口(interface)。 有更好的方法吗?

进一步的问题:

任何人都可以解释行 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

最佳答案

进一步问题 1

定义如下

typedef int (__stdcall * pICFUNC)(int);

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

Double = pICFUNC(lpfnGetProcessID);

pICFUNC 用于转换。

进一步的问题 2

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

int add(int num);

您可以实现以下功能:

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

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

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

编辑:一些实现提示

导入创建实例的函数

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

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

typedef MyClass* (__stdcall * pCREATINST)();

转换 lpfnCreateInstance

pCREATINST createInstance;

createInstance = pCREATINST(lpfnCreateInstance)

创建你的实例

MyClass *myInstance = creatInstance();

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

int res = myInstance->add(123);

你应该对 destroyInstance 做同样的事情,注意类型 请注意,我无法测试此代码,但它应该是正确的方法。

关于c++ - 将 C++ DLL 加载到调用另一个 DLL 中的函数的 matlab,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26928016/

相关文章:

c++ - Dll内存管理

assembly - 汇编代码中的返回地址

c - 如何跟踪所有本地函数调用和退出,并将其记录到文件中以供查看

python - SVN批量重命名空格问题

c++ - 无法理解为什么会出现段错误?

c++ - QThread 来回传递数据

c++ - (MSVC 2017/WALL &/WX) 包括 Iostream 产生 800 个警告

c - MATLAB 在 DLL 中调用函数时的堆栈限制是多少

c++ - 交换 std::list 中的相邻元素

c# - 从 C# asp.net 调用 Delphi XE6 unicode dll